linux/drivers/staging/dream/qdsp5/audio_in.c
<<
>>
Prefs
   1/* arch/arm/mach-msm/qdsp5/audio_in.c
   2 *
   3 * pcm audio input device
   4 *
   5 * Copyright (C) 2008 Google, Inc.
   6 * Copyright (C) 2008 HTC Corporation
   7 *
   8 * This software is licensed under the terms of the GNU General Public
   9 * License version 2, as published by the Free Software Foundation, and
  10 * may be copied, distributed, and modified under those terms.
  11 *
  12 * This program is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 * GNU General Public License for more details.
  16 *
  17 */
  18
  19#include <linux/module.h>
  20#include <linux/fs.h>
  21#include <linux/miscdevice.h>
  22#include <linux/uaccess.h>
  23#include <linux/kthread.h>
  24#include <linux/wait.h>
  25#include <linux/dma-mapping.h>
  26#include <linux/gfp.h>
  27
  28#include <linux/delay.h>
  29
  30#include <linux/msm_audio.h>
  31
  32#include <asm/atomic.h>
  33#include <asm/ioctls.h>
  34#include <mach/msm_adsp.h>
  35#include <mach/msm_rpcrouter.h>
  36
  37#include "audmgr.h"
  38
  39#include <mach/qdsp5/qdsp5audpreproccmdi.h>
  40#include <mach/qdsp5/qdsp5audpreprocmsg.h>
  41#include <mach/qdsp5/qdsp5audreccmdi.h>
  42#include <mach/qdsp5/qdsp5audrecmsg.h>
  43
  44/* for queue ids - should be relative to module number*/
  45#include "adsp.h"
  46
  47/* FRAME_NUM must be a power of two */
  48#define FRAME_NUM               (8)
  49#define FRAME_SIZE              (2052 * 2)
  50#define MONO_DATA_SIZE          (2048)
  51#define STEREO_DATA_SIZE        (MONO_DATA_SIZE * 2)
  52#define DMASZ                   (FRAME_SIZE * FRAME_NUM)
  53
  54#define AGC_PARAM_SIZE          (20)
  55#define NS_PARAM_SIZE           (6)
  56#define IIR_PARAM_SIZE          (48)
  57#define DEBUG                   (0)
  58
  59#define AGC_ENABLE   0x0001
  60#define NS_ENABLE    0x0002
  61#define IIR_ENABLE   0x0004
  62
  63struct tx_agc_config {
  64        uint16_t agc_params[AGC_PARAM_SIZE];
  65};
  66
  67struct ns_config {
  68        uint16_t ns_params[NS_PARAM_SIZE];
  69};
  70
  71struct tx_iir_filter {
  72        uint16_t num_bands;
  73        uint16_t iir_params[IIR_PARAM_SIZE];
  74};
  75
  76struct audpre_cmd_iir_config_type {
  77        uint16_t cmd_id;
  78        uint16_t active_flag;
  79        uint16_t num_bands;
  80        uint16_t iir_params[IIR_PARAM_SIZE];
  81};
  82
  83struct buffer {
  84        void *data;
  85        uint32_t size;
  86        uint32_t read;
  87        uint32_t addr;
  88};
  89
  90struct audio_in {
  91        struct buffer in[FRAME_NUM];
  92
  93        spinlock_t dsp_lock;
  94
  95        atomic_t in_bytes;
  96
  97        struct mutex lock;
  98        struct mutex read_lock;
  99        wait_queue_head_t wait;
 100
 101        struct msm_adsp_module *audpre;
 102        struct msm_adsp_module *audrec;
 103
 104        /* configuration to use on next enable */
 105        uint32_t samp_rate;
 106        uint32_t channel_mode;
 107        uint32_t buffer_size; /* 2048 for mono, 4096 for stereo */
 108        uint32_t type; /* 0 for PCM ,1 for AAC */
 109        uint32_t dsp_cnt;
 110        uint32_t in_head; /* next buffer dsp will write */
 111        uint32_t in_tail; /* next buffer read() will read */
 112        uint32_t in_count; /* number of buffers available to read() */
 113
 114        unsigned short samp_rate_index;
 115
 116        struct audmgr audmgr;
 117
 118        /* data allocated for various buffers */
 119        char *data;
 120        dma_addr_t phys;
 121
 122        int opened;
 123        int enabled;
 124        int running;
 125        int stopped; /* set when stopped, cleared on flush */
 126
 127        /* audpre settings */
 128        int agc_enable;
 129        struct tx_agc_config agc;
 130
 131        int ns_enable;
 132        struct ns_config ns;
 133
 134        int iir_enable;
 135        struct tx_iir_filter iir;
 136};
 137
 138static int audio_in_dsp_enable(struct audio_in *audio, int enable);
 139static int audio_in_encoder_config(struct audio_in *audio);
 140static int audio_dsp_read_buffer(struct audio_in *audio, uint32_t read_cnt);
 141static void audio_flush(struct audio_in *audio);
 142static int audio_dsp_set_agc(struct audio_in *audio);
 143static int audio_dsp_set_ns(struct audio_in *audio);
 144static int audio_dsp_set_tx_iir(struct audio_in *audio);
 145
 146static unsigned convert_dsp_samp_index(unsigned index)
 147{
 148        switch (index) {
 149        case 48000:     return AUDREC_CMD_SAMP_RATE_INDX_48000;
 150        case 44100:     return AUDREC_CMD_SAMP_RATE_INDX_44100;
 151        case 32000:     return AUDREC_CMD_SAMP_RATE_INDX_32000;
 152        case 24000:     return AUDREC_CMD_SAMP_RATE_INDX_24000;
 153        case 22050:     return AUDREC_CMD_SAMP_RATE_INDX_22050;
 154        case 16000:     return AUDREC_CMD_SAMP_RATE_INDX_16000;
 155        case 12000:     return AUDREC_CMD_SAMP_RATE_INDX_12000;
 156        case 11025:     return AUDREC_CMD_SAMP_RATE_INDX_11025;
 157        case 8000:      return AUDREC_CMD_SAMP_RATE_INDX_8000;
 158        default:        return AUDREC_CMD_SAMP_RATE_INDX_11025;
 159        }
 160}
 161
 162static unsigned convert_samp_rate(unsigned hz)
 163{
 164        switch (hz) {
 165        case 48000: return RPC_AUD_DEF_SAMPLE_RATE_48000;
 166        case 44100: return RPC_AUD_DEF_SAMPLE_RATE_44100;
 167        case 32000: return RPC_AUD_DEF_SAMPLE_RATE_32000;
 168        case 24000: return RPC_AUD_DEF_SAMPLE_RATE_24000;
 169        case 22050: return RPC_AUD_DEF_SAMPLE_RATE_22050;
 170        case 16000: return RPC_AUD_DEF_SAMPLE_RATE_16000;
 171        case 12000: return RPC_AUD_DEF_SAMPLE_RATE_12000;
 172        case 11025: return RPC_AUD_DEF_SAMPLE_RATE_11025;
 173        case 8000:  return RPC_AUD_DEF_SAMPLE_RATE_8000;
 174        default:    return RPC_AUD_DEF_SAMPLE_RATE_11025;
 175        }
 176}
 177
 178static unsigned convert_samp_index(unsigned index)
 179{
 180        switch (index) {
 181        case RPC_AUD_DEF_SAMPLE_RATE_48000:     return 48000;
 182        case RPC_AUD_DEF_SAMPLE_RATE_44100:     return 44100;
 183        case RPC_AUD_DEF_SAMPLE_RATE_32000:     return 32000;
 184        case RPC_AUD_DEF_SAMPLE_RATE_24000:     return 24000;
 185        case RPC_AUD_DEF_SAMPLE_RATE_22050:     return 22050;
 186        case RPC_AUD_DEF_SAMPLE_RATE_16000:     return 16000;
 187        case RPC_AUD_DEF_SAMPLE_RATE_12000:     return 12000;
 188        case RPC_AUD_DEF_SAMPLE_RATE_11025:     return 11025;
 189        case RPC_AUD_DEF_SAMPLE_RATE_8000:      return 8000;
 190        default:                                return 11025;
 191        }
 192}
 193
 194/* must be called with audio->lock held */
 195static int audio_in_enable(struct audio_in *audio)
 196{
 197        struct audmgr_config cfg;
 198        int rc;
 199
 200        if (audio->enabled)
 201                return 0;
 202
 203        cfg.tx_rate = audio->samp_rate;
 204        cfg.rx_rate = RPC_AUD_DEF_SAMPLE_RATE_NONE;
 205        cfg.def_method = RPC_AUD_DEF_METHOD_RECORD;
 206        if (audio->type == AUDREC_CMD_TYPE_0_INDEX_WAV)
 207                cfg.codec = RPC_AUD_DEF_CODEC_PCM;
 208        else
 209                cfg.codec = RPC_AUD_DEF_CODEC_AAC;
 210        cfg.snd_method = RPC_SND_METHOD_MIDI;
 211
 212        rc = audmgr_enable(&audio->audmgr, &cfg);
 213        if (rc < 0)
 214                return rc;
 215
 216        if (msm_adsp_enable(audio->audpre)) {
 217                pr_err("audrec: msm_adsp_enable(audpre) failed\n");
 218                return -ENODEV;
 219        }
 220        if (msm_adsp_enable(audio->audrec)) {
 221                pr_err("audrec: msm_adsp_enable(audrec) failed\n");
 222                return -ENODEV;
 223        }
 224
 225        audio->enabled = 1;
 226        audio_in_dsp_enable(audio, 1);
 227
 228        return 0;
 229}
 230
 231/* must be called with audio->lock held */
 232static int audio_in_disable(struct audio_in *audio)
 233{
 234        if (audio->enabled) {
 235                audio->enabled = 0;
 236
 237                audio_in_dsp_enable(audio, 0);
 238
 239                wake_up(&audio->wait);
 240
 241                msm_adsp_disable(audio->audrec);
 242                msm_adsp_disable(audio->audpre);
 243                audmgr_disable(&audio->audmgr);
 244        }
 245        return 0;
 246}
 247
 248/* ------------------- dsp --------------------- */
 249static void audpre_dsp_event(void *data, unsigned id, size_t len,
 250                            void (*getevent)(void *ptr, size_t len))
 251{
 252        uint16_t msg[2];
 253        getevent(msg, sizeof(msg));
 254
 255        switch (id) {
 256        case AUDPREPROC_MSG_CMD_CFG_DONE_MSG:
 257                pr_info("audpre: type %d, status_flag %d\n", msg[0], msg[1]);
 258                break;
 259        case AUDPREPROC_MSG_ERROR_MSG_ID:
 260                pr_info("audpre: err_index %d\n", msg[0]);
 261                break;
 262        default:
 263                pr_err("audpre: unknown event %d\n", id);
 264        }
 265}
 266
 267struct audio_frame {
 268        uint16_t count_low;
 269        uint16_t count_high;
 270        uint16_t bytes;
 271        uint16_t unknown;
 272        unsigned char samples[];
 273} __attribute__((packed));
 274
 275static void audio_in_get_dsp_frames(struct audio_in *audio)
 276{
 277        struct audio_frame *frame;
 278        uint32_t index;
 279        unsigned long flags;
 280
 281        index = audio->in_head;
 282
 283        /* XXX check for bogus frame size? */
 284
 285        frame = (void *) (((char *)audio->in[index].data) - sizeof(*frame));
 286
 287        spin_lock_irqsave(&audio->dsp_lock, flags);
 288        audio->in[index].size = frame->bytes;
 289
 290        audio->in_head = (audio->in_head + 1) & (FRAME_NUM - 1);
 291
 292        /* If overflow, move the tail index foward. */
 293        if (audio->in_head == audio->in_tail)
 294                audio->in_tail = (audio->in_tail + 1) & (FRAME_NUM - 1);
 295        else
 296                audio->in_count++;
 297
 298        audio_dsp_read_buffer(audio, audio->dsp_cnt++);
 299        spin_unlock_irqrestore(&audio->dsp_lock, flags);
 300
 301        wake_up(&audio->wait);
 302}
 303
 304static void audrec_dsp_event(void *data, unsigned id, size_t len,
 305                            void (*getevent)(void *ptr, size_t len))
 306{
 307        struct audio_in *audio = data;
 308        uint16_t msg[3];
 309        getevent(msg, sizeof(msg));
 310
 311        switch (id) {
 312        case AUDREC_MSG_CMD_CFG_DONE_MSG:
 313                if (msg[0] & AUDREC_MSG_CFG_DONE_TYPE_0_UPDATE) {
 314                        if (msg[0] & AUDREC_MSG_CFG_DONE_TYPE_0_ENA) {
 315                                pr_info("audpre: CFG ENABLED\n");
 316                                audio_dsp_set_agc(audio);
 317                                audio_dsp_set_ns(audio);
 318                                audio_dsp_set_tx_iir(audio);
 319                                audio_in_encoder_config(audio);
 320                        } else {
 321                                pr_info("audrec: CFG SLEEP\n");
 322                                audio->running = 0;
 323                        }
 324                } else {
 325                        pr_info("audrec: CMD_CFG_DONE %x\n", msg[0]);
 326                }
 327                break;
 328        case AUDREC_MSG_CMD_AREC_PARAM_CFG_DONE_MSG: {
 329                pr_info("audrec: PARAM CFG DONE\n");
 330                audio->running = 1;
 331                break;
 332        }
 333        case AUDREC_MSG_FATAL_ERR_MSG:
 334                pr_err("audrec: ERROR %x\n", msg[0]);
 335                break;
 336        case AUDREC_MSG_PACKET_READY_MSG:
 337/* REC_DBG("type %x, count %d", msg[0], (msg[1] | (msg[2] << 16))); */
 338                audio_in_get_dsp_frames(audio);
 339                break;
 340        default:
 341                pr_err("audrec: unknown event %d\n", id);
 342        }
 343}
 344
 345struct msm_adsp_ops audpre_adsp_ops = {
 346        .event = audpre_dsp_event,
 347};
 348
 349struct msm_adsp_ops audrec_adsp_ops = {
 350        .event = audrec_dsp_event,
 351};
 352
 353
 354#define audio_send_queue_pre(audio, cmd, len) \
 355        msm_adsp_write(audio->audpre, QDSP_uPAudPreProcCmdQueue, cmd, len)
 356#define audio_send_queue_recbs(audio, cmd, len) \
 357        msm_adsp_write(audio->audrec, QDSP_uPAudRecBitStreamQueue, cmd, len)
 358#define audio_send_queue_rec(audio, cmd, len) \
 359        msm_adsp_write(audio->audrec, \
 360        QDSP_uPAudRecCmdQueue, cmd, len)
 361
 362static int audio_dsp_set_agc(struct audio_in *audio)
 363{
 364        audpreproc_cmd_cfg_agc_params cmd;
 365
 366        memset(&cmd, 0, sizeof(cmd));
 367        cmd.cmd_id = AUDPREPROC_CMD_CFG_AGC_PARAMS;
 368
 369        if (audio->agc_enable) {
 370                /* cmd.tx_agc_param_mask = 0xFE00 from sample code */
 371                cmd.tx_agc_param_mask =
 372                (1 << AUDPREPROC_CMD_TX_AGC_PARAM_MASK_COMP_SLOPE) |
 373                (1 << AUDPREPROC_CMD_TX_AGC_PARAM_MASK_COMP_TH) |
 374                (1 << AUDPREPROC_CMD_TX_AGC_PARAM_MASK_EXP_SLOPE) |
 375                (1 << AUDPREPROC_CMD_TX_AGC_PARAM_MASK_EXP_TH) |
 376                (1 << AUDPREPROC_CMD_TX_AGC_PARAM_MASK_COMP_AIG_FLAG) |
 377                (1 << AUDPREPROC_CMD_TX_AGC_PARAM_MASK_COMP_STATIC_GAIN) |
 378                (1 << AUDPREPROC_CMD_TX_AGC_PARAM_MASK_TX_AGC_ENA_FLAG);
 379                cmd.tx_agc_enable_flag =
 380                        AUDPREPROC_CMD_TX_AGC_ENA_FLAG_ENA;
 381                memcpy(&cmd.static_gain, &audio->agc.agc_params[0],
 382                        sizeof(uint16_t) * 6);
 383                /* cmd.param_mask = 0xFFF0 from sample code */
 384                cmd.param_mask =
 385                        (1 << AUDPREPROC_CMD_PARAM_MASK_RMS_TAY) |
 386                        (1 << AUDPREPROC_CMD_PARAM_MASK_RELEASEK) |
 387                        (1 << AUDPREPROC_CMD_PARAM_MASK_DELAY) |
 388                        (1 << AUDPREPROC_CMD_PARAM_MASK_ATTACKK) |
 389                        (1 << AUDPREPROC_CMD_PARAM_MASK_LEAKRATE_SLOW) |
 390                        (1 << AUDPREPROC_CMD_PARAM_MASK_LEAKRATE_FAST) |
 391                        (1 << AUDPREPROC_CMD_PARAM_MASK_AIG_RELEASEK) |
 392                        (1 << AUDPREPROC_CMD_PARAM_MASK_AIG_MIN) |
 393                        (1 << AUDPREPROC_CMD_PARAM_MASK_AIG_MAX) |
 394                        (1 << AUDPREPROC_CMD_PARAM_MASK_LEAK_UP) |
 395                        (1 << AUDPREPROC_CMD_PARAM_MASK_LEAK_DOWN) |
 396                        (1 << AUDPREPROC_CMD_PARAM_MASK_AIG_ATTACKK);
 397                memcpy(&cmd.aig_attackk, &audio->agc.agc_params[6],
 398                        sizeof(uint16_t) * 14);
 399
 400        } else {
 401                cmd.tx_agc_param_mask =
 402                        (1 << AUDPREPROC_CMD_TX_AGC_PARAM_MASK_TX_AGC_ENA_FLAG);
 403                cmd.tx_agc_enable_flag =
 404                        AUDPREPROC_CMD_TX_AGC_ENA_FLAG_DIS;
 405        }
 406#if DEBUG
 407        pr_info("cmd_id = 0x%04x\n", cmd.cmd_id);
 408        pr_info("tx_agc_param_mask = 0x%04x\n", cmd.tx_agc_param_mask);
 409        pr_info("tx_agc_enable_flag = 0x%04x\n", cmd.tx_agc_enable_flag);
 410        pr_info("static_gain = 0x%04x\n", cmd.static_gain);
 411        pr_info("adaptive_gain_flag = 0x%04x\n", cmd.adaptive_gain_flag);
 412        pr_info("expander_th = 0x%04x\n", cmd.expander_th);
 413        pr_info("expander_slope = 0x%04x\n", cmd.expander_slope);
 414        pr_info("compressor_th = 0x%04x\n", cmd.compressor_th);
 415        pr_info("compressor_slope = 0x%04x\n", cmd.compressor_slope);
 416        pr_info("param_mask = 0x%04x\n", cmd.param_mask);
 417        pr_info("aig_attackk = 0x%04x\n", cmd.aig_attackk);
 418        pr_info("aig_leak_down = 0x%04x\n", cmd.aig_leak_down);
 419        pr_info("aig_leak_up = 0x%04x\n", cmd.aig_leak_up);
 420        pr_info("aig_max = 0x%04x\n", cmd.aig_max);
 421        pr_info("aig_min = 0x%04x\n", cmd.aig_min);
 422        pr_info("aig_releasek = 0x%04x\n", cmd.aig_releasek);
 423        pr_info("aig_leakrate_fast = 0x%04x\n", cmd.aig_leakrate_fast);
 424        pr_info("aig_leakrate_slow = 0x%04x\n", cmd.aig_leakrate_slow);
 425        pr_info("attackk_msw = 0x%04x\n", cmd.attackk_msw);
 426        pr_info("attackk_lsw = 0x%04x\n", cmd.attackk_lsw);
 427        pr_info("delay = 0x%04x\n", cmd.delay);
 428        pr_info("releasek_msw = 0x%04x\n", cmd.releasek_msw);
 429        pr_info("releasek_lsw = 0x%04x\n", cmd.releasek_lsw);
 430        pr_info("rms_tav = 0x%04x\n", cmd.rms_tav);
 431#endif
 432        return audio_send_queue_pre(audio, &cmd, sizeof(cmd));
 433}
 434
 435static int audio_dsp_set_ns(struct audio_in *audio)
 436{
 437        audpreproc_cmd_cfg_ns_params cmd;
 438
 439        memset(&cmd, 0, sizeof(cmd));
 440        cmd.cmd_id = AUDPREPROC_CMD_CFG_NS_PARAMS;
 441
 442        if (audio->ns_enable) {
 443                /* cmd.ec_mode_new is fixed as 0x0064 when enable from sample code */
 444                cmd.ec_mode_new =
 445                        AUDPREPROC_CMD_EC_MODE_NEW_NS_ENA |
 446                        AUDPREPROC_CMD_EC_MODE_NEW_HB_ENA |
 447                        AUDPREPROC_CMD_EC_MODE_NEW_VA_ENA;
 448                memcpy(&cmd.dens_gamma_n, &audio->ns.ns_params,
 449                        sizeof(audio->ns.ns_params));
 450        } else {
 451                cmd.ec_mode_new =
 452                        AUDPREPROC_CMD_EC_MODE_NEW_NLMS_DIS |
 453                        AUDPREPROC_CMD_EC_MODE_NEW_DES_DIS |
 454                        AUDPREPROC_CMD_EC_MODE_NEW_NS_DIS |
 455                        AUDPREPROC_CMD_EC_MODE_NEW_CNI_DIS |
 456                        AUDPREPROC_CMD_EC_MODE_NEW_NLES_DIS |
 457                        AUDPREPROC_CMD_EC_MODE_NEW_HB_DIS |
 458                        AUDPREPROC_CMD_EC_MODE_NEW_VA_DIS |
 459                        AUDPREPROC_CMD_EC_MODE_NEW_PCD_DIS |
 460                        AUDPREPROC_CMD_EC_MODE_NEW_FEHI_DIS |
 461                        AUDPREPROC_CMD_EC_MODE_NEW_NEHI_DIS |
 462                        AUDPREPROC_CMD_EC_MODE_NEW_NLPP_DIS |
 463                        AUDPREPROC_CMD_EC_MODE_NEW_FNE_DIS |
 464                        AUDPREPROC_CMD_EC_MODE_NEW_PRENLMS_DIS;
 465        }
 466#if DEBUG
 467        pr_info("cmd_id = 0x%04x\n", cmd.cmd_id);
 468        pr_info("ec_mode_new = 0x%04x\n", cmd.ec_mode_new);
 469        pr_info("dens_gamma_n = 0x%04x\n", cmd.dens_gamma_n);
 470        pr_info("dens_nfe_block_size = 0x%04x\n", cmd.dens_nfe_block_size);
 471        pr_info("dens_limit_ns = 0x%04x\n", cmd.dens_limit_ns);
 472        pr_info("dens_limit_ns_d = 0x%04x\n", cmd.dens_limit_ns_d);
 473        pr_info("wb_gamma_e = 0x%04x\n", cmd.wb_gamma_e);
 474        pr_info("wb_gamma_n = 0x%04x\n", cmd.wb_gamma_n);
 475#endif
 476        return audio_send_queue_pre(audio, &cmd, sizeof(cmd));
 477}
 478
 479static int audio_dsp_set_tx_iir(struct audio_in *audio)
 480{
 481        struct audpre_cmd_iir_config_type cmd;
 482
 483        memset(&cmd, 0, sizeof(cmd));
 484        cmd.cmd_id = AUDPREPROC_CMD_CFG_IIR_TUNING_FILTER_PARAMS;
 485
 486        if (audio->iir_enable) {
 487                cmd.active_flag = AUDPREPROC_CMD_IIR_ACTIVE_FLAG_ENA;
 488                cmd.num_bands = audio->iir.num_bands;
 489                memcpy(&cmd.iir_params, &audio->iir.iir_params,
 490                        sizeof(audio->iir.iir_params));
 491        } else {
 492                cmd.active_flag = AUDPREPROC_CMD_IIR_ACTIVE_FLAG_DIS;
 493        }
 494#if DEBUG
 495        pr_info("cmd_id = 0x%04x\n", cmd.cmd_id);
 496        pr_info("active_flag = 0x%04x\n", cmd.active_flag);
 497#endif
 498        return audio_send_queue_pre(audio, &cmd, sizeof(cmd));
 499}
 500
 501static int audio_in_dsp_enable(struct audio_in *audio, int enable)
 502{
 503        audrec_cmd_cfg cmd;
 504
 505        memset(&cmd, 0, sizeof(cmd));
 506        cmd.cmd_id = AUDREC_CMD_CFG;
 507        cmd.type_0 = enable ? AUDREC_CMD_TYPE_0_ENA : AUDREC_CMD_TYPE_0_DIS;
 508        cmd.type_0 |= (AUDREC_CMD_TYPE_0_UPDATE | audio->type);
 509        cmd.type_1 = 0;
 510
 511        return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
 512}
 513
 514static int audio_in_encoder_config(struct audio_in *audio)
 515{
 516        audrec_cmd_arec0param_cfg cmd;
 517        uint16_t *data = (void *) audio->data;
 518        unsigned n;
 519
 520        memset(&cmd, 0, sizeof(cmd));
 521        cmd.cmd_id = AUDREC_CMD_AREC0PARAM_CFG;
 522        cmd.ptr_to_extpkt_buffer_msw = audio->phys >> 16;
 523        cmd.ptr_to_extpkt_buffer_lsw = audio->phys;
 524        cmd.buf_len = FRAME_NUM; /* Both WAV and AAC use 8 frames */
 525        cmd.samp_rate_index = audio->samp_rate_index;
 526        cmd.stereo_mode = audio->channel_mode; /* 0 for mono, 1 for stereo */
 527
 528        /* FIXME have no idea why cmd.rec_quality is fixed
 529         * as 0x1C00 from sample code
 530         */
 531        cmd.rec_quality = 0x1C00;
 532
 533        /* prepare buffer pointers:
 534         * Mono: 1024 samples + 4 halfword header
 535         * Stereo: 2048 samples + 4 halfword header
 536         * AAC
 537         * Mono/Stere: 768 + 4 halfword header
 538         */
 539        for (n = 0; n < FRAME_NUM; n++) {
 540                audio->in[n].data = data + 4;
 541                if (audio->type == AUDREC_CMD_TYPE_0_INDEX_WAV)
 542                        data += (4 + (audio->channel_mode ? 2048 : 1024));
 543                else if (audio->type == AUDREC_CMD_TYPE_0_INDEX_AAC)
 544                        data += (4 + 768);
 545        }
 546
 547        return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
 548}
 549
 550static int audio_dsp_read_buffer(struct audio_in *audio, uint32_t read_cnt)
 551{
 552        audrec_cmd_packet_ext_ptr cmd;
 553
 554        memset(&cmd, 0, sizeof(cmd));
 555        cmd.cmd_id = AUDREC_CMD_PACKET_EXT_PTR;
 556        /* Both WAV and AAC use AUDREC_CMD_TYPE_0 */
 557        cmd.type = AUDREC_CMD_TYPE_0;
 558        cmd.curr_rec_count_msw = read_cnt >> 16;
 559        cmd.curr_rec_count_lsw = read_cnt;
 560
 561        return audio_send_queue_recbs(audio, &cmd, sizeof(cmd));
 562}
 563
 564/* ------------------- device --------------------- */
 565
 566static void audio_enable_agc(struct audio_in *audio, int enable)
 567{
 568        if (audio->agc_enable != enable) {
 569                audio->agc_enable = enable;
 570                if (audio->running)
 571                        audio_dsp_set_agc(audio);
 572        }
 573}
 574
 575static void audio_enable_ns(struct audio_in *audio, int enable)
 576{
 577        if (audio->ns_enable != enable) {
 578                audio->ns_enable = enable;
 579                if (audio->running)
 580                        audio_dsp_set_ns(audio);
 581        }
 582}
 583
 584static void audio_enable_tx_iir(struct audio_in *audio, int enable)
 585{
 586        if (audio->iir_enable != enable) {
 587                audio->iir_enable = enable;
 588                if (audio->running)
 589                        audio_dsp_set_tx_iir(audio);
 590        }
 591}
 592
 593static void audio_flush(struct audio_in *audio)
 594{
 595        int i;
 596
 597        audio->dsp_cnt = 0;
 598        audio->in_head = 0;
 599        audio->in_tail = 0;
 600        audio->in_count = 0;
 601        for (i = 0; i < FRAME_NUM; i++) {
 602                audio->in[i].size = 0;
 603                audio->in[i].read = 0;
 604        }
 605}
 606
 607static long audio_in_ioctl(struct file *file,
 608                                unsigned int cmd, unsigned long arg)
 609{
 610        struct audio_in *audio = file->private_data;
 611        int rc;
 612
 613        if (cmd == AUDIO_GET_STATS) {
 614                struct msm_audio_stats stats;
 615                stats.byte_count = atomic_read(&audio->in_bytes);
 616                if (copy_to_user((void *) arg, &stats, sizeof(stats)))
 617                        return -EFAULT;
 618                return 0;
 619        }
 620
 621        mutex_lock(&audio->lock);
 622        switch (cmd) {
 623        case AUDIO_START:
 624                rc = audio_in_enable(audio);
 625                break;
 626        case AUDIO_STOP:
 627                rc = audio_in_disable(audio);
 628                audio->stopped = 1;
 629                break;
 630        case AUDIO_FLUSH:
 631                if (audio->stopped) {
 632                        /* Make sure we're stopped and we wake any threads
 633                         * that might be blocked holding the read_lock.
 634                         * While audio->stopped read threads will always
 635                         * exit immediately.
 636                         */
 637                        wake_up(&audio->wait);
 638                        mutex_lock(&audio->read_lock);
 639                        audio_flush(audio);
 640                        mutex_unlock(&audio->read_lock);
 641                }
 642        case AUDIO_SET_CONFIG: {
 643                struct msm_audio_config cfg;
 644                if (copy_from_user(&cfg, (void *) arg, sizeof(cfg))) {
 645                        rc = -EFAULT;
 646                        break;
 647                }
 648                if (cfg.channel_count == 1) {
 649                        cfg.channel_count = AUDREC_CMD_STEREO_MODE_MONO;
 650                } else if (cfg.channel_count == 2) {
 651                        cfg.channel_count = AUDREC_CMD_STEREO_MODE_STEREO;
 652                } else {
 653                        rc = -EINVAL;
 654                        break;
 655                }
 656
 657                if (cfg.type == 0) {
 658                        cfg.type = AUDREC_CMD_TYPE_0_INDEX_WAV;
 659                } else if (cfg.type == 1) {
 660                        cfg.type = AUDREC_CMD_TYPE_0_INDEX_AAC;
 661                } else {
 662                        rc = -EINVAL;
 663                        break;
 664                }
 665                audio->samp_rate = convert_samp_rate(cfg.sample_rate);
 666                audio->samp_rate_index =
 667                  convert_dsp_samp_index(cfg.sample_rate);
 668                audio->channel_mode = cfg.channel_count;
 669                audio->buffer_size =
 670                                audio->channel_mode ? STEREO_DATA_SIZE
 671                                                        : MONO_DATA_SIZE;
 672                audio->type = cfg.type;
 673                rc = 0;
 674                break;
 675        }
 676        case AUDIO_GET_CONFIG: {
 677                struct msm_audio_config cfg;
 678                cfg.buffer_size = audio->buffer_size;
 679                cfg.buffer_count = FRAME_NUM;
 680                cfg.sample_rate = convert_samp_index(audio->samp_rate);
 681                if (audio->channel_mode == AUDREC_CMD_STEREO_MODE_MONO)
 682                        cfg.channel_count = 1;
 683                else
 684                        cfg.channel_count = 2;
 685                if (audio->type == AUDREC_CMD_TYPE_0_INDEX_WAV)
 686                        cfg.type = 0;
 687                else
 688                        cfg.type = 1;
 689                cfg.unused[0] = 0;
 690                cfg.unused[1] = 0;
 691                cfg.unused[2] = 0;
 692                if (copy_to_user((void *) arg, &cfg, sizeof(cfg)))
 693                        rc = -EFAULT;
 694                else
 695                        rc = 0;
 696                break;
 697        }
 698        default:
 699                rc = -EINVAL;
 700        }
 701        mutex_unlock(&audio->lock);
 702        return rc;
 703}
 704
 705static ssize_t audio_in_read(struct file *file,
 706                                char __user *buf,
 707                                size_t count, loff_t *pos)
 708{
 709        struct audio_in *audio = file->private_data;
 710        unsigned long flags;
 711        const char __user *start = buf;
 712        void *data;
 713        uint32_t index;
 714        uint32_t size;
 715        int rc = 0;
 716
 717        mutex_lock(&audio->read_lock);
 718        while (count > 0) {
 719                rc = wait_event_interruptible(
 720                        audio->wait, (audio->in_count > 0) || audio->stopped);
 721                if (rc < 0)
 722                        break;
 723
 724                if (audio->stopped) {
 725                        rc = -EBUSY;
 726                        break;
 727                }
 728
 729                index = audio->in_tail;
 730                data = (uint8_t *) audio->in[index].data;
 731                size = audio->in[index].size;
 732                if (count >= size) {
 733                        if (copy_to_user(buf, data, size)) {
 734                                rc = -EFAULT;
 735                                break;
 736                        }
 737                        spin_lock_irqsave(&audio->dsp_lock, flags);
 738                        if (index != audio->in_tail) {
 739                        /* overrun -- data is invalid and we need to retry */
 740                                spin_unlock_irqrestore(&audio->dsp_lock, flags);
 741                                continue;
 742                        }
 743                        audio->in[index].size = 0;
 744                        audio->in_tail = (audio->in_tail + 1) & (FRAME_NUM - 1);
 745                        audio->in_count--;
 746                        spin_unlock_irqrestore(&audio->dsp_lock, flags);
 747                        count -= size;
 748                        buf += size;
 749                        if (audio->type == AUDREC_CMD_TYPE_0_INDEX_AAC)
 750                                break;
 751                } else {
 752                        pr_err("audio_in: short read\n");
 753                        break;
 754                }
 755                if (audio->type == AUDREC_CMD_TYPE_0_INDEX_AAC)
 756                        break; /* AAC only read one frame */
 757        }
 758        mutex_unlock(&audio->read_lock);
 759
 760        if (buf > start)
 761                return buf - start;
 762
 763        return rc;
 764}
 765
 766static ssize_t audio_in_write(struct file *file,
 767                                const char __user *buf,
 768                                size_t count, loff_t *pos)
 769{
 770        return -EINVAL;
 771}
 772
 773static int audio_in_release(struct inode *inode, struct file *file)
 774{
 775        struct audio_in *audio = file->private_data;
 776
 777        mutex_lock(&audio->lock);
 778        audio_in_disable(audio);
 779        audio_flush(audio);
 780        msm_adsp_put(audio->audrec);
 781        msm_adsp_put(audio->audpre);
 782        audio->audrec = NULL;
 783        audio->audpre = NULL;
 784        audio->opened = 0;
 785        mutex_unlock(&audio->lock);
 786        return 0;
 787}
 788
 789static struct audio_in the_audio_in;
 790
 791static int audio_in_open(struct inode *inode, struct file *file)
 792{
 793        struct audio_in *audio = &the_audio_in;
 794        int rc;
 795
 796        mutex_lock(&audio->lock);
 797        if (audio->opened) {
 798                rc = -EBUSY;
 799                goto done;
 800        }
 801
 802        /* Settings will be re-config at AUDIO_SET_CONFIG,
 803         * but at least we need to have initial config
 804         */
 805        audio->samp_rate = RPC_AUD_DEF_SAMPLE_RATE_11025;
 806        audio->samp_rate_index = AUDREC_CMD_SAMP_RATE_INDX_11025;
 807        audio->channel_mode = AUDREC_CMD_STEREO_MODE_MONO;
 808        audio->buffer_size = MONO_DATA_SIZE;
 809        audio->type = AUDREC_CMD_TYPE_0_INDEX_WAV;
 810
 811        rc = audmgr_open(&audio->audmgr);
 812        if (rc)
 813                goto done;
 814        rc = msm_adsp_get("AUDPREPROCTASK", &audio->audpre,
 815                                &audpre_adsp_ops, audio);
 816        if (rc)
 817                goto done;
 818        rc = msm_adsp_get("AUDRECTASK", &audio->audrec,
 819                           &audrec_adsp_ops, audio);
 820        if (rc)
 821                goto done;
 822
 823        audio->dsp_cnt = 0;
 824        audio->stopped = 0;
 825
 826        audio_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 long audpre_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 837{
 838        struct audio_in *audio = file->private_data;
 839        int rc = 0, enable;
 840        uint16_t enable_mask;
 841#if DEBUG
 842        int i;
 843#endif
 844
 845        mutex_lock(&audio->lock);
 846        switch (cmd) {
 847        case AUDIO_ENABLE_AUDPRE: {
 848                if (copy_from_user(&enable_mask, (void *) arg,
 849                                sizeof(enable_mask)))
 850                        goto out_fault;
 851
 852                enable = (enable_mask & AGC_ENABLE) ? 1 : 0;
 853                audio_enable_agc(audio, enable);
 854                enable = (enable_mask & NS_ENABLE) ? 1 : 0;
 855                audio_enable_ns(audio, enable);
 856                enable = (enable_mask & IIR_ENABLE) ? 1 : 0;
 857                audio_enable_tx_iir(audio, enable);
 858                break;
 859        }
 860        case AUDIO_SET_AGC: {
 861                if (copy_from_user(&audio->agc, (void *) arg,
 862                                sizeof(audio->agc)))
 863                        goto out_fault;
 864#if DEBUG
 865                pr_info("set agc\n");
 866                for (i = 0; i < AGC_PARAM_SIZE; i++) \
 867                        pr_info("agc_params[%d] = 0x%04x\n", i,
 868                                audio->agc.agc_params[i]);
 869#endif
 870                break;
 871        }
 872        case AUDIO_SET_NS: {
 873                if (copy_from_user(&audio->ns, (void *) arg,
 874                                sizeof(audio->ns)))
 875                        goto out_fault;
 876#if DEBUG
 877                pr_info("set ns\n");
 878                for (i = 0; i < NS_PARAM_SIZE; i++) \
 879                        pr_info("ns_params[%d] = 0x%04x\n",
 880                                i, audio->ns.ns_params[i]);
 881#endif
 882                break;
 883        }
 884        case AUDIO_SET_TX_IIR: {
 885                if (copy_from_user(&audio->iir, (void *) arg,
 886                                sizeof(audio->iir)))
 887                        goto out_fault;
 888#if DEBUG
 889                pr_info("set iir\n");
 890                pr_info("iir.num_bands = 0x%04x\n", audio->iir.num_bands);
 891                for (i = 0; i < IIR_PARAM_SIZE; i++) \
 892                        pr_info("iir_params[%d] = 0x%04x\n",
 893                                i, audio->iir.iir_params[i]);
 894#endif
 895                break;
 896        }
 897        default:
 898                rc = -EINVAL;
 899        }
 900
 901        goto out;
 902
 903out_fault:
 904        rc = -EFAULT;
 905out:
 906        mutex_unlock(&audio->lock);
 907        return rc;
 908}
 909
 910static int audpre_open(struct inode *inode, struct file *file)
 911{
 912        struct audio_in *audio = &the_audio_in;
 913        file->private_data = audio;
 914        return 0;
 915}
 916
 917static struct file_operations audio_fops = {
 918        .owner          = THIS_MODULE,
 919        .open           = audio_in_open,
 920        .release        = audio_in_release,
 921        .read           = audio_in_read,
 922        .write          = audio_in_write,
 923        .unlocked_ioctl = audio_in_ioctl,
 924};
 925
 926static struct file_operations audpre_fops = {
 927        .owner          = THIS_MODULE,
 928        .open           = audpre_open,
 929        .unlocked_ioctl = audpre_ioctl,
 930};
 931
 932struct miscdevice audio_in_misc = {
 933        .minor  = MISC_DYNAMIC_MINOR,
 934        .name   = "msm_pcm_in",
 935        .fops   = &audio_fops,
 936};
 937
 938struct miscdevice audpre_misc = {
 939        .minor  = MISC_DYNAMIC_MINOR,
 940        .name   = "msm_audpre",
 941        .fops   = &audpre_fops,
 942};
 943
 944static int __init audio_in_init(void)
 945{
 946        int rc;
 947        the_audio_in.data = dma_alloc_coherent(NULL, DMASZ,
 948                                               &the_audio_in.phys, GFP_KERNEL);
 949        if (!the_audio_in.data) {
 950                printk(KERN_ERR "%s: Unable to allocate DMA buffer\n",
 951                       __func__);
 952                return -ENOMEM;
 953        }
 954
 955        mutex_init(&the_audio_in.lock);
 956        mutex_init(&the_audio_in.read_lock);
 957        spin_lock_init(&the_audio_in.dsp_lock);
 958        init_waitqueue_head(&the_audio_in.wait);
 959        rc = misc_register(&audio_in_misc);
 960        if (!rc) {
 961                rc = misc_register(&audpre_misc);
 962                if (rc < 0)
 963                        misc_deregister(&audio_in_misc);
 964        }
 965        return rc;
 966}
 967
 968device_initcall(audio_in_init);
 969
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.