PageRenderTime 411ms CodeModel.GetById 16ms RepoModel.GetById 2ms app.codeStats 0ms

/arch/arm/mach-msm/qdsp5/audio_voicememo.c

https://bitbucket.org/sammyz/iscream_thunderc-2.6.35-rebase
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
  1. /* arch/arm/mach-msm/qdsp5/audio_voicememo.c
  2. *
  3. * Voice Memo device
  4. *
  5. * Copyright (C) 2008 Google, Inc.
  6. * Copyright (C) 2008 HTC Corporation
  7. * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
  8. *
  9. * This code is based in part on arch/arm/mach-msm/qdsp5/audio_mp3.c
  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. #include <linux/module.h>
  25. #include <linux/fs.h>
  26. #include <linux/miscdevice.h>
  27. #include <linux/uaccess.h>
  28. #include <linux/kthread.h>
  29. #include <linux/wait.h>
  30. #include <linux/dma-mapping.h>
  31. #include <linux/delay.h>
  32. #include <linux/msm_audio_voicememo.h>
  33. #include <linux/slab.h>
  34. #include <asm/atomic.h>
  35. #include <asm/ioctls.h>
  36. #include <mach/msm_rpcrouter.h>
  37. #include <mach/debug_mm.h>
  38. #include "audmgr.h"
  39. #define SND_PROG_VERS "rs30000002:0x00020001"
  40. #define SND_PROG 0x30000002
  41. #define SND_VERS_COMP 0x00020001
  42. #define SND_VOC_REC_START_PROC 19
  43. #define SND_VOC_REC_STOP_PROC 20
  44. #define SND_VOC_REC_PAUSE_PROC 21
  45. #define SND_VOC_REC_RESUME_PROC 22
  46. #define SND_VOC_REC_PUT_BUF_PROC 23
  47. #define SND_VOC_REC_AV_SYNC_CB_PTR_PROC 9
  48. #define SND_VOC_REC_CB_FUNC_TYPE_PROC 10
  49. #define REC_CLIENT_DATA 0x11223344
  50. #define DATA_CB_FUNC_ID 0x12345678
  51. #define AV_SYNC_CB_FUNC_ID 0x87654321
  52. #define CLIENT_DATA 0xaabbccdd
  53. #define RPC_TYPE_REQUEST 0
  54. #define RPC_TYPE_REPLY 1
  55. #define RPC_STATUS_FAILURE 0
  56. #define RPC_STATUS_SUCCESS 1
  57. #define RPC_VERSION 2
  58. #define RPC_COMMON_HDR_SZ (sizeof(uint32_t) * 2)
  59. #define RPC_REQUEST_HDR_SZ (sizeof(struct rpc_request_hdr))
  60. #define RPC_REPLY_HDR_SZ (sizeof(uint32_t) * 3)
  61. #define RPC_REPLY_SZ (sizeof(uint32_t) * 6)
  62. #define MAX_FRAME_SIZE 36 /* QCELP - 36, AMRNB - 32, EVRC - 24 */
  63. #define MAX_REC_BUF_COUNT 5 /* Maximum supported voc rec buffers */
  64. #define MAX_REC_BUF_SIZE (MAX_FRAME_SIZE * 10)
  65. #define MAX_VOICEMEMO_BUF_SIZE \
  66. ((MAX_REC_BUF_SIZE)*MAX_REC_BUF_COUNT) /* 5 buffers for 200ms frame */
  67. #define MSM_AUD_BUFFER_UPDATE_WAIT_MS 2000
  68. enum rpc_voc_rec_status_type {
  69. RPC_VOC_REC_STAT_SUCCESS = 1,
  70. RPC_VOC_REC_STAT_DONE = 2,
  71. RPC_VOC_REC_STAT_AUTO_STOP = 4,
  72. RPC_VOC_REC_STAT_PAUSED = 8,
  73. RPC_VOC_REC_STAT_RESUMED = 16,
  74. RPC_VOC_REC_STAT_ERROR = 32,
  75. RPC_VOC_REC_STAT_BUFFER_ERROR = 64,
  76. RPC_VOC_REC_STAT_INVALID_PARAM = 128,
  77. RPC_VOC_REC_STAT_INT_TIME = 256,
  78. RPC_VOC_REC_STAT_DATA = 512,
  79. RPC_VOC_REC_STAT_NOT_READY = 1024,
  80. RPC_VOC_REC_STAT_INFORM_EVRC = 2048,
  81. RPC_VOC_REC_STAT_INFORM_13K = 4096,
  82. RPC_VOC_REC_STAT_INFORM_AMR = 8192,
  83. RPC_VOC_REC_STAT_INFORM_MAX = 65535
  84. };
  85. struct rpc_snd_voc_rec_start_args {
  86. uint32_t param_status; /* 1 = valid, 0 = not valid */
  87. uint32_t rec_type;
  88. uint32_t rec_interval_ms;
  89. uint32_t auto_stop_ms;
  90. uint32_t capability;
  91. uint32_t max_rate;
  92. uint32_t min_rate;
  93. uint32_t frame_format;
  94. uint32_t dtx_enable;
  95. uint32_t data_req_ms;
  96. uint32_t rec_client_data;
  97. uint32_t cb_func_id;
  98. uint32_t sync_cb_func_id;
  99. uint32_t client_data;
  100. };
  101. struct rpc_snd_voc_rec_put_buf_args {
  102. uint32_t buf;
  103. uint32_t num_bytes;
  104. };
  105. struct snd_voc_rec_start_msg {
  106. struct rpc_request_hdr hdr;
  107. struct rpc_snd_voc_rec_start_args args;
  108. };
  109. struct snd_voc_rec_put_buf_msg {
  110. struct rpc_request_hdr hdr;
  111. struct rpc_snd_voc_rec_put_buf_args args;
  112. };
  113. struct snd_voc_rec_av_sync_cb_func_data {
  114. uint32_t sync_cb_func_id;
  115. uint32_t status; /* Pointer status (1 = valid, 0 = invalid) */
  116. uint32_t num_samples;
  117. uint32_t time_stamp[2];
  118. uint32_t lost_samples;
  119. uint32_t frame_index;
  120. uint32_t client_data;
  121. };
  122. struct snd_voc_rec_cb_func_fw_data {
  123. uint32_t fw_ptr_status; /* FW Pointer status (1=valid,0=invalid) */
  124. uint32_t rec_buffer_size;
  125. uint32_t data[MAX_REC_BUF_SIZE/4];
  126. uint32_t rec_buffer_size_copy;
  127. uint32_t rec_num_frames; /* Number of voice frames */
  128. uint32_t rec_length; /* Valid data in record buffer =
  129. * data_req_ms amount of data */
  130. uint32_t client_data; /* A11 rec buffer pointer */
  131. uint32_t rw_ptr_status; /* RW Pointer status (1=valid,0=invalid) */
  132. };
  133. struct snd_voc_rec_cb_func_rw_data {
  134. uint32_t fw_ptr_status; /* FW Pointer status (1=valid,0=invalid) */
  135. uint32_t rw_ptr_status; /* RW Pointer status (1=valid,0=invalid) */
  136. uint32_t rec_buffer_size;
  137. uint32_t data[MAX_REC_BUF_SIZE/4];
  138. uint32_t rec_buffer_size_copy;
  139. uint32_t rec_num_frames; /* Number of voice frames */
  140. uint32_t rec_length; /* Valid data in record buffer =
  141. * data_req_ms amount of data */
  142. uint32_t client_data; /* A11 rec buffer pointer */
  143. };
  144. struct snd_voc_rec_data_cb_func_data {
  145. uint32_t cb_func_id;
  146. uint32_t status; /* Pointer status (1 = valid, 0 = invalid) */
  147. uint32_t rec_status;
  148. union {
  149. struct snd_voc_rec_cb_func_fw_data fw_data;
  150. struct snd_voc_rec_cb_func_rw_data rw_data;
  151. } pkt;
  152. };
  153. struct buffer {
  154. void *data;
  155. unsigned size;
  156. unsigned used; /* Usage actual recorded data */
  157. unsigned addr;
  158. unsigned numframes;
  159. };
  160. struct audio_voicememo {
  161. uint32_t byte_count; /* Pass statistics to user space for
  162. * time stamping */
  163. uint32_t frame_count;
  164. int opened;
  165. int enabled;
  166. int running;
  167. int stopped;
  168. int pause_resume;
  169. uint32_t rpc_prog;
  170. uint32_t rpc_ver;
  171. uint32_t rpc_xid;
  172. uint32_t rpc_status;
  173. struct mutex lock;
  174. struct mutex read_lock;
  175. struct mutex dsp_lock;
  176. wait_queue_head_t read_wait;
  177. wait_queue_head_t wait;
  178. struct buffer in[MAX_REC_BUF_COUNT];
  179. char *rec_buf_ptr;
  180. dma_addr_t phys;
  181. uint32_t rec_buf_size;
  182. uint8_t read_next; /* index to input buffers to be read next */
  183. uint8_t fill_next; /* index to buffer that should be filled as
  184. * data comes from A9 */
  185. struct audmgr audmgr;
  186. struct msm_audio_voicememo_config voicememo_cfg;
  187. struct msm_rpc_endpoint *sndept;
  188. struct task_struct *task;
  189. };
  190. static struct audio_voicememo the_audio_voicememo;
  191. static int audvoicememo_validate_usr_config(
  192. struct msm_audio_voicememo_config *config)
  193. {
  194. int rc = -1; /* error */
  195. if (config->rec_type != RPC_VOC_REC_FORWARD &&
  196. config->rec_type != RPC_VOC_REC_REVERSE &&
  197. config->rec_type != RPC_VOC_REC_BOTH)
  198. goto done;
  199. /* QCELP, EVRC, AMR-NB only */
  200. if (config->capability != RPC_VOC_CAP_IS733 &&
  201. config->capability != RPC_VOC_CAP_IS127 &&
  202. config->capability != RPC_VOC_CAP_AMR)
  203. goto done;
  204. /* QCP, AMR format supported */
  205. if ((config->frame_format != RPC_VOC_PB_NATIVE_QCP) &&
  206. (config->frame_format != RPC_VOC_PB_AMR))
  207. goto done;
  208. if ((config->frame_format == RPC_VOC_PB_AMR) &&
  209. (config->capability != RPC_VOC_CAP_AMR))
  210. goto done;
  211. /* To make sure, max kernel buf size matches
  212. * with max data request time */
  213. if (config->data_req_ms > ((MAX_REC_BUF_SIZE/MAX_FRAME_SIZE)*20))
  214. goto done;
  215. rc = 0;
  216. done:
  217. return rc;
  218. }
  219. static void audvoicememo_flush_buf(struct audio_voicememo *audio)
  220. {
  221. uint8_t index;
  222. for (index = 0; index < MAX_REC_BUF_COUNT; index++)
  223. audio->in[index].used = 0;
  224. audio->read_next = 0;
  225. audio->fill_next = 0;
  226. }
  227. static void audvoicememo_ioport_reset(struct audio_voicememo *audio)
  228. {
  229. /* Make sure read/write thread are free from
  230. * sleep and knowing that system is not able
  231. * to process io request at the moment
  232. */
  233. wake_up(&audio->read_wait);
  234. mutex_lock(&audio->read_lock);
  235. audvoicememo_flush_buf(audio);
  236. mutex_unlock(&audio->read_lock);
  237. }
  238. /* must be called with audio->lock held */
  239. static int audvoicememo_enable(struct audio_voicememo *audio)
  240. {
  241. struct audmgr_config cfg;
  242. struct snd_voc_rec_put_buf_msg bmsg;
  243. struct snd_voc_rec_start_msg msg;
  244. uint8_t index;
  245. uint32_t offset = 0;
  246. int rc;
  247. if (audio->enabled)
  248. return 0;
  249. /* Codec / method configure to audmgr client */
  250. cfg.tx_rate = RPC_AUD_DEF_SAMPLE_RATE_8000;
  251. cfg.rx_rate = RPC_AUD_DEF_SAMPLE_RATE_NONE;
  252. cfg.def_method = RPC_AUD_DEF_METHOD_RECORD;
  253. if (audio->voicememo_cfg.capability == RPC_VOC_CAP_IS733)
  254. cfg.codec = RPC_AUD_DEF_CODEC_VOC_13K;
  255. else if (audio->voicememo_cfg.capability == RPC_VOC_CAP_IS127)
  256. cfg.codec = RPC_AUD_DEF_CODEC_VOC_EVRC;
  257. else
  258. cfg.codec = RPC_AUD_DEF_CODEC_VOC_AMR; /* RPC_VOC_CAP_AMR */
  259. cfg.snd_method = RPC_SND_METHOD_VOICE;
  260. rc = audmgr_enable(&audio->audmgr, &cfg);
  261. if (rc < 0)
  262. return rc;
  263. /* Configure VOC Rec buffer */
  264. for (index = 0; index < MAX_REC_BUF_COUNT; index++) {
  265. audio->in[index].data = audio->rec_buf_ptr + offset;
  266. audio->in[index].addr = audio->phys + offset;
  267. audio->in[index].size = audio->rec_buf_size;
  268. audio->in[index].used = 0;
  269. audio->in[index].numframes = 0;
  270. offset += audio->rec_buf_size;
  271. bmsg.args.buf = (uint32_t) audio->in[index].data;
  272. bmsg.args.num_bytes = cpu_to_be32(audio->in[index].size);
  273. MM_DBG("rec_buf_ptr=0x%8x, rec_buf_size = 0x%8x\n",
  274. bmsg.args.buf, bmsg.args.num_bytes);
  275. msm_rpc_setup_req(&bmsg.hdr, audio->rpc_prog, audio->rpc_ver,
  276. SND_VOC_REC_PUT_BUF_PROC);
  277. audio->rpc_xid = bmsg.hdr.xid;
  278. audio->rpc_status = RPC_STATUS_FAILURE;
  279. msm_rpc_write(audio->sndept, &bmsg, sizeof(bmsg));
  280. rc = wait_event_timeout(audio->wait,
  281. audio->rpc_status != RPC_STATUS_FAILURE, 1 * HZ);
  282. if (rc == 0)
  283. goto err;
  284. }
  285. /* Start Recording */
  286. msg.args.param_status = cpu_to_be32(0x00000001);
  287. msg.args.rec_type = cpu_to_be32(audio->voicememo_cfg.rec_type);
  288. msg.args.rec_interval_ms =
  289. cpu_to_be32(audio->voicememo_cfg.rec_interval_ms);
  290. msg.args.auto_stop_ms = cpu_to_be32(audio->voicememo_cfg.auto_stop_ms);
  291. msg.args.capability = cpu_to_be32(audio->voicememo_cfg.capability);
  292. msg.args.max_rate = cpu_to_be32(audio->voicememo_cfg.max_rate);
  293. msg.args.min_rate = cpu_to_be32(audio->voicememo_cfg.min_rate);
  294. msg.args.frame_format = cpu_to_be32(audio->voicememo_cfg.frame_format);
  295. msg.args.dtx_enable = cpu_to_be32(audio->voicememo_cfg.dtx_enable);
  296. msg.args.data_req_ms = cpu_to_be32(audio->voicememo_cfg.data_req_ms);
  297. msg.args.rec_client_data = cpu_to_be32(REC_CLIENT_DATA);
  298. msg.args.cb_func_id = cpu_to_be32(DATA_CB_FUNC_ID);
  299. msg.args.sync_cb_func_id = cpu_to_be32(AV_SYNC_CB_FUNC_ID);
  300. msg.args.client_data = cpu_to_be32(CLIENT_DATA);
  301. msm_rpc_setup_req(&msg.hdr, audio->rpc_prog, audio->rpc_ver,
  302. SND_VOC_REC_START_PROC);
  303. audio->rpc_xid = msg.hdr.xid;
  304. audio->rpc_status = RPC_STATUS_FAILURE;
  305. msm_rpc_write(audio->sndept, &msg, sizeof(msg));
  306. rc = wait_event_timeout(audio->wait,
  307. audio->rpc_status != RPC_STATUS_FAILURE, 1 * HZ);
  308. if (rc == 0)
  309. goto err;
  310. audio->rpc_xid = 0;
  311. audio->enabled = 1;
  312. return 0;
  313. err:
  314. audio->rpc_xid = 0;
  315. audmgr_disable(&audio->audmgr);
  316. MM_ERR("Fail\n");
  317. return -1;
  318. }
  319. /* must be called with audio->lock held */
  320. static int audvoicememo_disable(struct audio_voicememo *audio)
  321. {
  322. struct rpc_request_hdr rhdr;
  323. int rc = 0;
  324. if (audio->enabled) {
  325. msm_rpc_setup_req(&rhdr, audio->rpc_prog, audio->rpc_ver,
  326. SND_VOC_REC_STOP_PROC);
  327. rc = msm_rpc_write(audio->sndept, &rhdr, sizeof(rhdr));
  328. wait_event_timeout(audio->wait, audio->stopped == 0,
  329. 1 * HZ);
  330. wake_up(&audio->read_wait);
  331. audmgr_disable(&audio->audmgr);
  332. audio->enabled = 0;
  333. }
  334. return 0;
  335. }
  336. /* RPC Reply Generator */
  337. static void rpc_reply(struct msm_rpc_endpoint *ept, uint32_t xid)
  338. {
  339. int rc = 0;
  340. uint8_t reply_buf[sizeof(struct rpc_reply_hdr)];
  341. struct rpc_reply_hdr *reply = (struct rpc_reply_hdr *)reply_buf;
  342. MM_DBG("inside\n");
  343. reply->xid = cpu_to_be32(xid);
  344. reply->type = cpu_to_be32(RPC_TYPE_REPLY); /* reply */
  345. reply->reply_stat = cpu_to_be32(RPCMSG_REPLYSTAT_ACCEPTED);
  346. reply->data.acc_hdr.accept_stat = cpu_to_be32(RPC_ACCEPTSTAT_SUCCESS);
  347. reply->data.acc_hdr.verf_flavor = 0;
  348. reply->data.acc_hdr.verf_length = 0;
  349. rc = msm_rpc_write(ept, reply_buf, sizeof(reply_buf));
  350. if (rc < 0)
  351. MM_ERR("could not write RPC response: %d\n", rc);
  352. }
  353. static void process_rpc_request(uint32_t proc, uint32_t xid,
  354. void *data, int len, void *private)
  355. {
  356. struct audio_voicememo *audio = private;
  357. MM_DBG("inside\n");
  358. /* Sending Ack before processing the request
  359. * to make sure A9 get response immediate
  360. * However, if there is validation of request planned
  361. * may be move this reply Ack at the end */
  362. rpc_reply(audio->sndept, xid);
  363. switch (proc) {
  364. case SND_VOC_REC_AV_SYNC_CB_PTR_PROC: {
  365. MM_DBG("AV Sync CB:func_id=0x%8x,status=0x%x\n",
  366. be32_to_cpu(( \
  367. (struct snd_voc_rec_av_sync_cb_func_data *)\
  368. data)->sync_cb_func_id),\
  369. be32_to_cpu(( \
  370. (struct snd_voc_rec_av_sync_cb_func_data *)\
  371. data)->status));
  372. break;
  373. }
  374. case SND_VOC_REC_CB_FUNC_TYPE_PROC: {
  375. struct snd_voc_rec_data_cb_func_data *datacb_data
  376. = (void *)(data);
  377. struct snd_voc_rec_put_buf_msg bmsg;
  378. uint32_t rec_status = be32_to_cpu(datacb_data->rec_status);
  379. MM_DBG("Data CB:func_id=0x%8x,status=0x%x,\
  380. rec_status=0x%x\n",
  381. be32_to_cpu(datacb_data->cb_func_id),\
  382. be32_to_cpu(datacb_data->status),\
  383. be32_to_cpu(datacb_data->rec_status));
  384. /* Data recorded */
  385. if ((rec_status == RPC_VOC_REC_STAT_DATA) ||
  386. (rec_status == RPC_VOC_REC_STAT_DONE)) {
  387. if (datacb_data->pkt.fw_data.fw_ptr_status &&
  388. be32_to_cpu(datacb_data->pkt.fw_data.rec_length)) {
  389. MM_DBG("Copy FW link:rec_buf_size \
  390. = 0x%08x, rec_length=0x%08x\n",
  391. be32_to_cpu( \
  392. datacb_data->pkt.fw_data. \
  393. rec_buffer_size_copy),\
  394. be32_to_cpu(datacb_data->pkt.fw_data. \
  395. rec_length));
  396. mutex_lock(&audio->dsp_lock);
  397. memcpy(audio->in[audio->fill_next].data, \
  398. &(datacb_data->pkt.fw_data.data[0]), \
  399. be32_to_cpu(
  400. datacb_data->pkt.fw_data.rec_length));
  401. audio->in[audio->fill_next].used =
  402. be32_to_cpu(
  403. datacb_data->pkt.fw_data.rec_length);
  404. audio->in[audio->fill_next].numframes =
  405. be32_to_cpu(
  406. datacb_data->pkt.fw_data.rec_num_frames);
  407. mutex_unlock(&audio->dsp_lock);
  408. } else if (datacb_data->pkt.rw_data.rw_ptr_status &&
  409. be32_to_cpu(datacb_data->pkt.rw_data.rec_length)) {
  410. MM_DBG("Copy RW link:rec_buf_size \
  411. =0x%08x, rec_length=0x%08x\n",
  412. be32_to_cpu( \
  413. datacb_data->pkt.rw_data. \
  414. rec_buffer_size_copy),\
  415. be32_to_cpu(datacb_data->pkt.rw_data. \
  416. rec_length));
  417. mutex_lock(&audio->dsp_lock);
  418. memcpy(audio->in[audio->fill_next].data, \
  419. &(datacb_data->pkt.rw_data.data[0]), \
  420. be32_to_cpu(
  421. datacb_data->pkt.rw_data.rec_length));
  422. audio->in[audio->fill_next].used =
  423. be32_to_cpu(
  424. datacb_data->pkt.rw_data.rec_length);
  425. audio->in[audio->fill_next].numframes =
  426. be32_to_cpu(
  427. datacb_data->pkt.rw_data.rec_num_frames);
  428. mutex_unlock(&audio->dsp_lock);
  429. }
  430. if (rec_status != RPC_VOC_REC_STAT_DONE) {
  431. /* Not end of record */
  432. bmsg.args.buf = \
  433. (uint32_t) audio->in[audio->fill_next].data;
  434. bmsg.args.num_bytes = \
  435. be32_to_cpu(audio->in[audio->fill_next].size);
  436. if (++audio->fill_next == MAX_REC_BUF_COUNT)
  437. audio->fill_next = 0;
  438. msm_rpc_setup_req(&bmsg.hdr, audio->rpc_prog,
  439. audio->rpc_ver, SND_VOC_REC_PUT_BUF_PROC);
  440. msm_rpc_write(audio->sndept, &bmsg,
  441. sizeof(bmsg));
  442. wake_up(&audio->read_wait);
  443. } else {
  444. /* Indication record stopped gracefully */
  445. MM_DBG("End Of Voice Record\n");
  446. wake_up(&audio->wait);
  447. }
  448. } else if (rec_status == RPC_VOC_REC_STAT_PAUSED) {
  449. MM_DBG(" Voice Record PAUSED\n");
  450. audio->pause_resume = 1;
  451. } else if (rec_status == RPC_VOC_REC_STAT_RESUMED) {
  452. MM_DBG(" Voice Record RESUMED\n");
  453. audio->pause_resume = 0;
  454. } else if ((rec_status == RPC_VOC_REC_STAT_ERROR) ||
  455. (rec_status == RPC_VOC_REC_STAT_INVALID_PARAM) ||
  456. (rec_status == RPC_VOC_REC_STAT_BUFFER_ERROR))
  457. MM_ERR("error recording =0x%8x\n",
  458. rec_status);
  459. else if (rec_status == RPC_VOC_REC_STAT_INT_TIME)
  460. MM_DBG("Frames recorded matches interval \
  461. callback time\n");
  462. else if (rec_status == RPC_VOC_REC_STAT_AUTO_STOP) {
  463. MM_DBG(" Voice Record AUTO STOP\n");
  464. wake_up(&audio->read_wait);
  465. audmgr_disable(&audio->audmgr);
  466. audio->stopped = 1;
  467. audvoicememo_ioport_reset(audio);
  468. audio->stopped = 0;
  469. audio->enabled = 0;
  470. }
  471. break;
  472. }
  473. default:
  474. MM_ERR("UNKNOWN PROC , proc = 0x%8x \n", proc);
  475. }
  476. }
  477. static int voicememo_rpc_thread(void *data)
  478. {
  479. struct audio_voicememo *audio = data;
  480. struct rpc_request_hdr *hdr = NULL;
  481. uint32_t type;
  482. int len;
  483. MM_DBG("start\n");
  484. while (!kthread_should_stop()) {
  485. kfree(hdr);
  486. hdr = NULL;
  487. len = msm_rpc_read(audio->sndept, (void **) &hdr, -1, -1);
  488. MM_DBG("rpc_read len = 0x%x\n", len);
  489. if (len < 0) {
  490. MM_ERR("rpc read failed (%d)\n", len);
  491. break;
  492. }
  493. if (len < RPC_COMMON_HDR_SZ)
  494. continue;
  495. type = be32_to_cpu(hdr->type);
  496. if (type == RPC_TYPE_REPLY) {
  497. struct rpc_reply_hdr *rep = (void *) hdr;
  498. uint32_t status;
  499. if (len < RPC_REPLY_HDR_SZ)
  500. continue;
  501. status = be32_to_cpu(rep->reply_stat);
  502. if (status == RPCMSG_REPLYSTAT_ACCEPTED) {
  503. status =
  504. be32_to_cpu(rep->data.acc_hdr.accept_stat);
  505. /* Confirm major RPC success during open*/
  506. if ((audio->enabled == 0) &&
  507. (status == RPC_ACCEPTSTAT_SUCCESS) &&
  508. (audio->rpc_xid == rep->xid)) {
  509. audio->rpc_status = \
  510. RPC_STATUS_SUCCESS;
  511. wake_up(&audio->wait);
  512. }
  513. MM_DBG("rpc_reply status 0x%8x\n", status);
  514. } else {
  515. MM_ERR("rpc_reply denied!\n");
  516. }
  517. /* process reply */
  518. continue;
  519. } else if (type == RPC_TYPE_REQUEST) {
  520. if (len < RPC_REQUEST_HDR_SZ)
  521. continue;
  522. process_rpc_request(be32_to_cpu(hdr->procedure),
  523. be32_to_cpu(hdr->xid),
  524. (void *) (hdr + 1),
  525. len - sizeof(*hdr),
  526. audio);
  527. } else
  528. MM_ERR("Unexpected type (%d)\n", type);
  529. }
  530. MM_DBG("stop\n");
  531. kfree(hdr);
  532. hdr = NULL;
  533. return 0;
  534. }
  535. /* ------------------- device --------------------- */
  536. static long audio_voicememo_ioctl(struct file *file,
  537. unsigned int cmd, unsigned long arg)
  538. {
  539. struct audio_voicememo *audio = file->private_data;
  540. int rc = 0;
  541. if (cmd == AUDIO_GET_STATS) {
  542. struct msm_audio_stats stats;
  543. mutex_lock(&audio->dsp_lock);
  544. stats.byte_count = audio->byte_count;
  545. stats.sample_count = audio->frame_count;
  546. mutex_unlock(&audio->dsp_lock);
  547. if (copy_to_user((void *) arg, &stats, sizeof(stats)))
  548. return -EFAULT;
  549. return 0;
  550. }
  551. mutex_lock(&audio->lock);
  552. switch (cmd) {
  553. case AUDIO_START: {
  554. MM_DBG("AUDIO_START\n");
  555. audio->byte_count = 0;
  556. audio->frame_count = 0;
  557. if (audio->voicememo_cfg.rec_type != RPC_VOC_REC_NONE)
  558. rc = audvoicememo_enable(audio);
  559. else
  560. rc = -EINVAL;
  561. MM_DBG("AUDIO_START rc %d\n", rc);
  562. break;
  563. }
  564. case AUDIO_STOP: {
  565. MM_DBG("AUDIO_STOP\n");
  566. rc = audvoicememo_disable(audio);
  567. audio->stopped = 1;
  568. audvoicememo_ioport_reset(audio);
  569. audio->stopped = 0;
  570. MM_DBG("AUDIO_STOP rc %d\n", rc);
  571. break;
  572. }
  573. case AUDIO_GET_CONFIG: {
  574. struct msm_audio_config cfg;
  575. MM_DBG("AUDIO_GET_CONFIG\n");
  576. cfg.buffer_size = audio->rec_buf_size;
  577. cfg.buffer_count = MAX_REC_BUF_COUNT;
  578. cfg.sample_rate = 8000; /* Voice Encoder works on 8k,
  579. * Mono */
  580. cfg.channel_count = 1;
  581. cfg.type = 0;
  582. cfg.unused[0] = 0;
  583. cfg.unused[1] = 0;
  584. cfg.unused[2] = 0;
  585. if (copy_to_user((void *) arg, &cfg, sizeof(cfg)))
  586. rc = -EFAULT;
  587. else
  588. rc = 0;
  589. MM_DBG("AUDIO_GET_CONFIG rc %d\n", rc);
  590. break;
  591. }
  592. case AUDIO_GET_VOICEMEMO_CONFIG: {
  593. MM_DBG("AUDIO_GET_VOICEMEMO_CONFIG\n");
  594. if (copy_to_user((void *)arg, &audio->voicememo_cfg,
  595. sizeof(audio->voicememo_cfg)))
  596. rc = -EFAULT;
  597. else
  598. rc = 0;
  599. MM_DBG("AUDIO_GET_VOICEMEMO_CONFIG rc %d\n", rc);
  600. break;
  601. }
  602. case AUDIO_SET_VOICEMEMO_CONFIG: {
  603. struct msm_audio_voicememo_config usr_config;
  604. MM_DBG("AUDIO_SET_VOICEMEMO_CONFIG\n");
  605. if (copy_from_user
  606. (&usr_config, (void *)arg,
  607. sizeof(usr_config))) {
  608. rc = -EFAULT;
  609. break;
  610. }
  611. if (audvoicememo_validate_usr_config(&usr_config)
  612. == 0) {
  613. audio->voicememo_cfg = usr_config;
  614. rc = 0;
  615. } else
  616. rc = -EINVAL;
  617. MM_DBG("AUDIO_SET_VOICEMEMO_CONFIG rc %d\n", rc);
  618. break;
  619. }
  620. case AUDIO_PAUSE: {
  621. struct rpc_request_hdr rhdr;
  622. MM_DBG("AUDIO_PAUSE\n");
  623. if (arg == 1)
  624. msm_rpc_setup_req(&rhdr, audio->rpc_prog,
  625. audio->rpc_ver, SND_VOC_REC_PAUSE_PROC);
  626. else
  627. msm_rpc_setup_req(&rhdr, audio->rpc_prog,
  628. audio->rpc_ver, SND_VOC_REC_RESUME_PROC);
  629. rc = msm_rpc_write(audio->sndept, &rhdr, sizeof(rhdr));
  630. MM_DBG("AUDIO_PAUSE exit %d\n", rc);
  631. break;
  632. }
  633. default:
  634. MM_ERR("IOCTL %d not supported\n", cmd);
  635. rc = -EINVAL;
  636. }
  637. mutex_unlock(&audio->lock);
  638. return rc;
  639. }
  640. static ssize_t audio_voicememo_read(struct file *file,
  641. char __user *buf,
  642. size_t count, loff_t *pos)
  643. {
  644. struct audio_voicememo *audio = file->private_data;
  645. const char __user *start = buf;
  646. int rc = 0;
  647. mutex_lock(&audio->read_lock);
  648. MM_DBG("buff read =0x%8x \n", count);
  649. while (count > 0) {
  650. rc = wait_event_interruptible_timeout(audio->read_wait,
  651. (audio->in[audio->read_next].used > 0) ||
  652. (audio->stopped),
  653. msecs_to_jiffies(MSM_AUD_BUFFER_UPDATE_WAIT_MS));
  654. if (rc == 0) {
  655. rc = -ETIMEDOUT;
  656. break;
  657. } else if (rc < 0)
  658. break;
  659. if (audio->stopped) {
  660. rc = -EBUSY;
  661. break;
  662. }
  663. if (count < audio->in[audio->read_next].used) {
  664. /* Read must happen in frame boundary. Since driver does
  665. * not split frames, read count must be greater or
  666. * equal to size of existing frames to copy
  667. */
  668. MM_DBG("read not in frame boundary\n");
  669. break;
  670. } else {
  671. mutex_lock(&audio->dsp_lock);
  672. dma_coherent_post_ops();
  673. if (copy_to_user
  674. (buf, audio->in[audio->read_next].data,
  675. audio->in[audio->read_next].used)) {
  676. MM_ERR("invalid addr %x \n", (unsigned int)buf);
  677. rc = -EFAULT;
  678. mutex_unlock(&audio->dsp_lock);
  679. break;
  680. }
  681. count -= audio->in[audio->read_next].used;
  682. audio->byte_count += audio->in[audio->read_next].used;
  683. audio->frame_count +=
  684. audio->in[audio->read_next].numframes;
  685. buf += audio->in[audio->read_next].used;
  686. audio->in[audio->read_next].used = 0;
  687. mutex_unlock(&audio->dsp_lock);
  688. if ((++audio->read_next) == MAX_REC_BUF_COUNT)
  689. audio->read_next = 0;
  690. if (audio->in[audio->read_next].used == 0)
  691. break; /* No data ready at this moment
  692. * Exit while loop to prevent
  693. * output thread sleep too long
  694. */
  695. }
  696. }
  697. mutex_unlock(&audio->read_lock);
  698. if (buf > start)
  699. rc = buf - start;
  700. MM_DBG("exit return =0x%8x\n", rc);
  701. return rc;
  702. }
  703. static ssize_t audio_voicememo_write(struct file *file,
  704. const char __user *buf,
  705. size_t count, loff_t *pos)
  706. {
  707. return -EINVAL;
  708. }
  709. static int audio_voicememo_release(struct inode *inode, struct file *file)
  710. {
  711. struct audio_voicememo *audio = file->private_data;
  712. mutex_lock(&audio->lock);
  713. audvoicememo_disable(audio);
  714. audvoicememo_flush_buf(audio);
  715. audio->opened = 0;
  716. mutex_unlock(&audio->lock);
  717. return 0;
  718. }
  719. static int audio_voicememo_open(struct inode *inode, struct file *file)
  720. {
  721. struct audio_voicememo *audio = &the_audio_voicememo;
  722. int rc;
  723. mutex_lock(&audio->lock);
  724. if (audio->opened) {
  725. rc = -EBUSY;
  726. goto done;
  727. }
  728. rc = audmgr_open(&audio->audmgr);
  729. if (rc)
  730. goto done;
  731. /*Set default param to None*/
  732. memset(&audio->voicememo_cfg, 0, sizeof(audio->voicememo_cfg));
  733. file->private_data = audio;
  734. audio->opened = 1;
  735. rc = 0;
  736. done:
  737. mutex_unlock(&audio->lock);
  738. return rc;
  739. }
  740. static const struct file_operations audio_fops = {
  741. .owner = THIS_MODULE,
  742. .open = audio_voicememo_open,
  743. .release = audio_voicememo_release,
  744. .read = audio_voicememo_read,
  745. .write = audio_voicememo_write,
  746. .unlocked_ioctl = audio_voicememo_ioctl,
  747. };
  748. struct miscdevice audio_voicememo_misc = {
  749. .minor = MISC_DYNAMIC_MINOR,
  750. .name = "msm_voicememo",
  751. .fops = &audio_fops,
  752. };
  753. static int audio_voicememo_probe(struct platform_device *pdev)
  754. {
  755. int rc;
  756. if (pdev->id != (SND_VERS_COMP & RPC_VERSION_MAJOR_MASK))
  757. return -EINVAL;
  758. mutex_init(&the_audio_voicememo.lock);
  759. mutex_init(&the_audio_voicememo.read_lock);
  760. mutex_init(&the_audio_voicememo.dsp_lock);
  761. init_waitqueue_head(&the_audio_voicememo.read_wait);
  762. init_waitqueue_head(&the_audio_voicememo.wait);
  763. the_audio_voicememo.rec_buf_ptr = dma_alloc_coherent(NULL,
  764. MAX_VOICEMEMO_BUF_SIZE,
  765. &the_audio_voicememo.phys, GFP_KERNEL);
  766. if (the_audio_voicememo.rec_buf_ptr == NULL) {
  767. MM_ERR("error allocating memory\n");
  768. rc = -ENOMEM;
  769. return rc;
  770. }
  771. the_audio_voicememo.rec_buf_size = MAX_REC_BUF_SIZE;
  772. MM_DBG("rec_buf_ptr = 0x%8x, phys = 0x%8x \n",
  773. (uint32_t) the_audio_voicememo.rec_buf_ptr, \
  774. the_audio_voicememo.phys);
  775. the_audio_voicememo.sndept = msm_rpc_connect_compatible(SND_PROG,
  776. SND_VERS_COMP, MSM_RPC_UNINTERRUPTIBLE);
  777. if (IS_ERR(the_audio_voicememo.sndept)) {
  778. MM_ERR("connect failed with compatible VERS = %x \n",
  779. SND_VERS_COMP);
  780. rc = PTR_ERR(the_audio_voicememo.sndept);
  781. the_audio_voicememo.sndept = NULL;
  782. MM_ERR("Failed to connect to snd svc\n");
  783. goto err;
  784. }
  785. the_audio_voicememo.task = kthread_run(voicememo_rpc_thread,
  786. &the_audio_voicememo, "voicememo_rpc");
  787. if (IS_ERR(the_audio_voicememo.task)) {
  788. rc = PTR_ERR(the_audio_voicememo.task);
  789. the_audio_voicememo.task = NULL;
  790. msm_rpc_close(the_audio_voicememo.sndept);
  791. the_audio_voicememo.sndept = NULL;
  792. MM_ERR("Failed to create voicememo_rpc task\n");
  793. goto err;
  794. }
  795. the_audio_voicememo.rpc_prog = SND_PROG;
  796. the_audio_voicememo.rpc_ver = SND_VERS_COMP;
  797. return misc_register(&audio_voicememo_misc);
  798. err:
  799. dma_free_coherent(NULL, MAX_VOICEMEMO_BUF_SIZE,
  800. the_audio_voicememo.rec_buf_ptr,
  801. the_audio_voicememo.phys);
  802. the_audio_voicememo.rec_buf_ptr = NULL;
  803. return rc;
  804. }
  805. static void __exit audio_voicememo_exit(void)
  806. {
  807. /* Close the RPC connection to make thread to comeout */
  808. msm_rpc_close(the_audio_voicememo.sndept);
  809. the_audio_voicememo.sndept = NULL;
  810. kthread_stop(the_audio_voicememo.task);
  811. the_audio_voicememo.task = NULL;
  812. if (the_audio_voicememo.rec_buf_ptr)
  813. dma_free_coherent(NULL, MAX_VOICEMEMO_BUF_SIZE,
  814. the_audio_voicememo.rec_buf_ptr,
  815. the_audio_voicememo.phys);
  816. the_audio_voicememo.rec_buf_ptr = NULL;
  817. misc_deregister(&audio_voicememo_misc);
  818. }
  819. static char audio_voicememo_rpc_name[] = "rs00000000";
  820. static struct platform_driver audio_voicememo_driver = {
  821. .probe = audio_voicememo_probe,
  822. .driver = {
  823. .owner = THIS_MODULE,
  824. },
  825. };
  826. static int __init audio_voicememo_init(void)
  827. {
  828. snprintf(audio_voicememo_rpc_name, sizeof(audio_voicememo_rpc_name),
  829. "rs%08x", SND_PROG);
  830. audio_voicememo_driver.driver.name = audio_voicememo_rpc_name;
  831. return platform_driver_register(&audio_voicememo_driver);
  832. }
  833. module_init(audio_voicememo_init);
  834. module_exit(audio_voicememo_exit);
  835. MODULE_DESCRIPTION("MSM Voice Memo driver");
  836. MODULE_LICENSE("GPL v2");
  837. MODULE_AUTHOR("QUALCOMM");