/arch/arm/mach-msm/qdsp5/audio_voicememo.c
C | 951 lines | 776 code | 114 blank | 61 comment | 115 complexity | 520974a4ca201cfe82dfdb12a95c95d0 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
- /* arch/arm/mach-msm/qdsp5/audio_voicememo.c
- *
- * Voice Memo device
- *
- * Copyright (C) 2008 Google, Inc.
- * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
- *
- * This code is based in part on arch/arm/mach-msm/qdsp5/audio_mp3.c
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * See the GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, you can find it at http://www.fsf.org.
- *
- */
- #include <linux/module.h>
- #include <linux/fs.h>
- #include <linux/miscdevice.h>
- #include <linux/uaccess.h>
- #include <linux/kthread.h>
- #include <linux/wait.h>
- #include <linux/dma-mapping.h>
- #include <linux/delay.h>
- #include <linux/msm_audio_voicememo.h>
- #include <linux/slab.h>
- #include <asm/atomic.h>
- #include <asm/ioctls.h>
- #include <mach/msm_rpcrouter.h>
- #include <mach/debug_mm.h>
- #include "audmgr.h"
- #define SND_PROG_VERS "rs30000002:0x00020001"
- #define SND_PROG 0x30000002
- #define SND_VERS_COMP 0x00020001
- #define SND_VOC_REC_START_PROC 19
- #define SND_VOC_REC_STOP_PROC 20
- #define SND_VOC_REC_PAUSE_PROC 21
- #define SND_VOC_REC_RESUME_PROC 22
- #define SND_VOC_REC_PUT_BUF_PROC 23
- #define SND_VOC_REC_AV_SYNC_CB_PTR_PROC 9
- #define SND_VOC_REC_CB_FUNC_TYPE_PROC 10
- #define REC_CLIENT_DATA 0x11223344
- #define DATA_CB_FUNC_ID 0x12345678
- #define AV_SYNC_CB_FUNC_ID 0x87654321
- #define CLIENT_DATA 0xaabbccdd
- #define RPC_TYPE_REQUEST 0
- #define RPC_TYPE_REPLY 1
- #define RPC_STATUS_FAILURE 0
- #define RPC_STATUS_SUCCESS 1
- #define RPC_VERSION 2
- #define RPC_COMMON_HDR_SZ (sizeof(uint32_t) * 2)
- #define RPC_REQUEST_HDR_SZ (sizeof(struct rpc_request_hdr))
- #define RPC_REPLY_HDR_SZ (sizeof(uint32_t) * 3)
- #define RPC_REPLY_SZ (sizeof(uint32_t) * 6)
- #define MAX_FRAME_SIZE 36 /* QCELP - 36, AMRNB - 32, EVRC - 24 */
- #define MAX_REC_BUF_COUNT 5 /* Maximum supported voc rec buffers */
- #define MAX_REC_BUF_SIZE (MAX_FRAME_SIZE * 10)
- #define MAX_VOICEMEMO_BUF_SIZE \
- ((MAX_REC_BUF_SIZE)*MAX_REC_BUF_COUNT) /* 5 buffers for 200ms frame */
- #define MSM_AUD_BUFFER_UPDATE_WAIT_MS 2000
- enum rpc_voc_rec_status_type {
- RPC_VOC_REC_STAT_SUCCESS = 1,
- RPC_VOC_REC_STAT_DONE = 2,
- RPC_VOC_REC_STAT_AUTO_STOP = 4,
- RPC_VOC_REC_STAT_PAUSED = 8,
- RPC_VOC_REC_STAT_RESUMED = 16,
- RPC_VOC_REC_STAT_ERROR = 32,
- RPC_VOC_REC_STAT_BUFFER_ERROR = 64,
- RPC_VOC_REC_STAT_INVALID_PARAM = 128,
- RPC_VOC_REC_STAT_INT_TIME = 256,
- RPC_VOC_REC_STAT_DATA = 512,
- RPC_VOC_REC_STAT_NOT_READY = 1024,
- RPC_VOC_REC_STAT_INFORM_EVRC = 2048,
- RPC_VOC_REC_STAT_INFORM_13K = 4096,
- RPC_VOC_REC_STAT_INFORM_AMR = 8192,
- RPC_VOC_REC_STAT_INFORM_MAX = 65535
- };
- struct rpc_snd_voc_rec_start_args {
- uint32_t param_status; /* 1 = valid, 0 = not valid */
- uint32_t rec_type;
- uint32_t rec_interval_ms;
- uint32_t auto_stop_ms;
- uint32_t capability;
- uint32_t max_rate;
- uint32_t min_rate;
- uint32_t frame_format;
- uint32_t dtx_enable;
- uint32_t data_req_ms;
- uint32_t rec_client_data;
- uint32_t cb_func_id;
- uint32_t sync_cb_func_id;
- uint32_t client_data;
- };
- struct rpc_snd_voc_rec_put_buf_args {
- uint32_t buf;
- uint32_t num_bytes;
- };
- struct snd_voc_rec_start_msg {
- struct rpc_request_hdr hdr;
- struct rpc_snd_voc_rec_start_args args;
- };
- struct snd_voc_rec_put_buf_msg {
- struct rpc_request_hdr hdr;
- struct rpc_snd_voc_rec_put_buf_args args;
- };
- struct snd_voc_rec_av_sync_cb_func_data {
- uint32_t sync_cb_func_id;
- uint32_t status; /* Pointer status (1 = valid, 0 = invalid) */
- uint32_t num_samples;
- uint32_t time_stamp[2];
- uint32_t lost_samples;
- uint32_t frame_index;
- uint32_t client_data;
- };
- struct snd_voc_rec_cb_func_fw_data {
- uint32_t fw_ptr_status; /* FW Pointer status (1=valid,0=invalid) */
- uint32_t rec_buffer_size;
- uint32_t data[MAX_REC_BUF_SIZE/4];
- uint32_t rec_buffer_size_copy;
- uint32_t rec_num_frames; /* Number of voice frames */
- uint32_t rec_length; /* Valid data in record buffer =
- * data_req_ms amount of data */
- uint32_t client_data; /* A11 rec buffer pointer */
- uint32_t rw_ptr_status; /* RW Pointer status (1=valid,0=invalid) */
- };
- struct snd_voc_rec_cb_func_rw_data {
- uint32_t fw_ptr_status; /* FW Pointer status (1=valid,0=invalid) */
- uint32_t rw_ptr_status; /* RW Pointer status (1=valid,0=invalid) */
- uint32_t rec_buffer_size;
- uint32_t data[MAX_REC_BUF_SIZE/4];
- uint32_t rec_buffer_size_copy;
- uint32_t rec_num_frames; /* Number of voice frames */
- uint32_t rec_length; /* Valid data in record buffer =
- * data_req_ms amount of data */
- uint32_t client_data; /* A11 rec buffer pointer */
- };
- struct snd_voc_rec_data_cb_func_data {
- uint32_t cb_func_id;
- uint32_t status; /* Pointer status (1 = valid, 0 = invalid) */
- uint32_t rec_status;
- union {
- struct snd_voc_rec_cb_func_fw_data fw_data;
- struct snd_voc_rec_cb_func_rw_data rw_data;
- } pkt;
- };
- struct buffer {
- void *data;
- unsigned size;
- unsigned used; /* Usage actual recorded data */
- unsigned addr;
- unsigned numframes;
- };
- struct audio_voicememo {
- uint32_t byte_count; /* Pass statistics to user space for
- * time stamping */
- uint32_t frame_count;
- int opened;
- int enabled;
- int running;
- int stopped;
- int pause_resume;
- uint32_t rpc_prog;
- uint32_t rpc_ver;
- uint32_t rpc_xid;
- uint32_t rpc_status;
- struct mutex lock;
- struct mutex read_lock;
- struct mutex dsp_lock;
- wait_queue_head_t read_wait;
- wait_queue_head_t wait;
- struct buffer in[MAX_REC_BUF_COUNT];
- char *rec_buf_ptr;
- dma_addr_t phys;
- uint32_t rec_buf_size;
- uint8_t read_next; /* index to input buffers to be read next */
- uint8_t fill_next; /* index to buffer that should be filled as
- * data comes from A9 */
- struct audmgr audmgr;
- struct msm_audio_voicememo_config voicememo_cfg;
- struct msm_rpc_endpoint *sndept;
- struct task_struct *task;
- };
- static struct audio_voicememo the_audio_voicememo;
- static int audvoicememo_validate_usr_config(
- struct msm_audio_voicememo_config *config)
- {
- int rc = -1; /* error */
- if (config->rec_type != RPC_VOC_REC_FORWARD &&
- config->rec_type != RPC_VOC_REC_REVERSE &&
- config->rec_type != RPC_VOC_REC_BOTH)
- goto done;
- /* QCELP, EVRC, AMR-NB only */
- if (config->capability != RPC_VOC_CAP_IS733 &&
- config->capability != RPC_VOC_CAP_IS127 &&
- config->capability != RPC_VOC_CAP_AMR)
- goto done;
- /* QCP, AMR format supported */
- if ((config->frame_format != RPC_VOC_PB_NATIVE_QCP) &&
- (config->frame_format != RPC_VOC_PB_AMR))
- goto done;
- if ((config->frame_format == RPC_VOC_PB_AMR) &&
- (config->capability != RPC_VOC_CAP_AMR))
-