msm-pcm.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647
  1. /* sound/soc/msm/msm-pcm.c
  2. *
  3. * Copyright (C) 2008 Google, Inc.
  4. * Copyright (C) 2008 HTC Corporation
  5. * Copyright (c) 2008-2009, 2012 The Linux Foundation. All rights reserved.
  6. *
  7. * This software is licensed under the terms of the GNU General Public
  8. * License version 2, as published by the Free Software Foundation, and
  9. * may be copied, distributed, and modified under those terms.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  14. *
  15. * See the GNU General Public License for more details.
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, you can find it at http://www.fsf.org.
  18. */
  19. #include <linux/init.h>
  20. #include <linux/err.h>
  21. #include <linux/module.h>
  22. #include <linux/moduleparam.h>
  23. #include <linux/time.h>
  24. #include <linux/wait.h>
  25. #include <linux/platform_device.h>
  26. #include <sound/core.h>
  27. #include <sound/soc.h>
  28. #include <sound/pcm.h>
  29. #include <sound/initval.h>
  30. #include <asm/dma.h>
  31. #include <linux/dma-mapping.h>
  32. #include "msm-pcm.h"
  33. #define MAX_DATA_SIZE 496
  34. #define AUDPP_ALSA_DECODER (-1)
  35. #define DB_TABLE_INDEX (50)
  36. #define audio_send_queue_recbs(prtd, cmd, len) \
  37. msm_adsp_write(prtd->audrec, QDSP_uPAudRecBitStreamQueue, cmd, len)
  38. #define audio_send_queue_rec(prtd, cmd, len) \
  39. msm_adsp_write(prtd->audrec, QDSP_uPAudRecCmdQueue, cmd, len)
  40. int intcnt;
  41. struct audio_frame {
  42. uint16_t count_low;
  43. uint16_t count_high;
  44. uint16_t bytes;
  45. uint16_t unknown;
  46. unsigned char samples[];
  47. } __attribute__ ((packed));
  48. /* Table contains dB to raw value mapping */
  49. static const unsigned decoder_db_table[] = {
  50. 31 , /* -50 dB */
  51. 35 , 39 , 44 , 50 , 56 ,
  52. 63 , 70 , 79 , 89 , 99 ,
  53. 112 , 125 , 141 , 158 , 177 ,
  54. 199 , 223 , 251 , 281 , 316 ,
  55. 354 , 398 , 446 , 501 , 562 ,
  56. 630 , 707 , 794 , 891 , 999 ,
  57. 1122 , 1258 , 1412 , 1584 , 1778 ,
  58. 1995 , 2238 , 2511 , 2818 , 3162 ,
  59. 3548 , 3981 , 4466 , 5011 , 5623 ,
  60. 6309 , 7079 , 7943 , 8912 , 10000 ,
  61. 11220 , 12589 , 14125 , 15848 , 17782 ,
  62. 19952 , 22387 , 25118 , 28183 , 31622 ,
  63. 35481 , 39810 , 44668 , 50118 , 56234 ,
  64. 63095 , 70794 , 79432 , 89125 , 100000 ,
  65. 112201 , 125892 , 141253 , 158489 , 177827 ,
  66. 199526 , 223872 , 251188 , 281838 , 316227 ,
  67. 354813 , 398107 , 446683 , 501187 , 562341 ,
  68. 630957 , 707945 , 794328 , 891250 , 1000000 ,
  69. 1122018 , 1258925 , 1412537 , 1584893 , 1778279 ,
  70. 1995262 , 2238721 , 2511886 , 2818382 , 3162277 ,
  71. 3548133 /* 51 dB */
  72. };
  73. static unsigned compute_db_raw(int db)
  74. {
  75. unsigned reg_val = 0; /* Computed result for correspondent db */
  76. /* Check if the given db is out of range */
  77. if (db <= MIN_DB)
  78. return 0;
  79. else if (db > MAX_DB)
  80. db = MAX_DB; /* If db is too high then set to max */
  81. reg_val = decoder_db_table[DB_TABLE_INDEX+db];
  82. return reg_val;
  83. }
  84. int msm_audio_volume_update(unsigned id,
  85. int volume, int pan)
  86. {
  87. unsigned vol_raw;
  88. vol_raw = compute_db_raw(volume);
  89. printk(KERN_INFO "volume: %8x vol_raw: %8x \n", volume, vol_raw);
  90. return audpp_set_volume_and_pan(id, vol_raw, pan);
  91. }
  92. EXPORT_SYMBOL(msm_audio_volume_update);
  93. void alsa_dsp_event(void *data, unsigned id, uint16_t *msg)
  94. {
  95. struct msm_audio *prtd = data;
  96. struct buffer *frame;
  97. unsigned long flag;
  98. switch (id) {
  99. case AUDPP_MSG_STATUS_MSG:
  100. break;
  101. case AUDPP_MSG_SPA_BANDS:
  102. break;
  103. case AUDPP_MSG_HOST_PCM_INTF_MSG:{
  104. unsigned id = msg[2];
  105. unsigned idx = msg[3] - 1;
  106. if (id != AUDPP_MSG_HOSTPCM_ID_ARM_RX) {
  107. printk(KERN_ERR "bogus id\n");
  108. break;
  109. }
  110. if (idx > 1) {
  111. printk(KERN_ERR "bogus buffer idx\n");
  112. break;
  113. }
  114. /* Update with actual sent buffer size */
  115. if (prtd->out[idx].used != BUF_INVALID_LEN)
  116. prtd->pcm_irq_pos += prtd->out[idx].used;
  117. if (prtd->pcm_irq_pos > prtd->pcm_size)
  118. prtd->pcm_irq_pos = prtd->pcm_count;
  119. if (prtd->ops->playback)
  120. prtd->ops->playback(prtd);
  121. if (prtd->mmap_flag)
  122. break;
  123. spin_lock_irqsave(&the_locks.write_dsp_lock, flag);
  124. if (prtd->running) {
  125. prtd->out[idx].used = 0;
  126. frame = prtd->out + prtd->out_tail;
  127. if (frame->used) {
  128. alsa_dsp_send_buffer(prtd,
  129. prtd->out_tail,
  130. frame->used);
  131. prtd->out_tail ^= 1;
  132. } else {
  133. prtd->out_needed++;
  134. }
  135. wake_up(&the_locks.write_wait);
  136. }
  137. spin_unlock_irqrestore(&the_locks.write_dsp_lock, flag);
  138. break;
  139. }
  140. case AUDPP_MSG_PCMDMAMISSED:
  141. pr_info("alsa_dsp_event: PCMDMAMISSED %d\n", msg[0]);
  142. prtd->eos_ack = 1;
  143. wake_up(&the_locks.eos_wait);
  144. break;
  145. case AUDPP_MSG_CFG_MSG:
  146. if (msg[0] == AUDPP_MSG_ENA_ENA) {
  147. prtd->out_needed = 0;
  148. prtd->running = 1;
  149. audio_dsp_out_enable(prtd, 1);
  150. } else if (msg[0] == AUDPP_MSG_ENA_DIS) {
  151. prtd->running = 0;
  152. } else {
  153. printk(KERN_ERR "alsa_dsp_event:CFG_MSG=%d\n", msg[0]);
  154. }
  155. break;
  156. case EVENT_MSG_ID:
  157. printk(KERN_INFO"alsa_dsp_event: arm9 event\n");
  158. break;
  159. default:
  160. printk(KERN_ERR "alsa_dsp_event: UNKNOWN (%d)\n", id);
  161. }
  162. }
  163. void alsa_audpre_dsp_event(void *data, unsigned id, size_t len,
  164. void (*getevent) (void *ptr, size_t len))
  165. {
  166. uint16_t msg[MAX_DATA_SIZE/2];
  167. if (len > MAX_DATA_SIZE) {
  168. printk(KERN_ERR"audpre: event too large(%d bytes)\n", len);
  169. return;
  170. }
  171. getevent(msg, len);
  172. switch (id) {
  173. case AUDPREPROC_MSG_CMD_CFG_DONE_MSG:
  174. break;
  175. case AUDPREPROC_MSG_ERROR_MSG_ID:
  176. printk(KERN_ERR "audpre: err_index %d\n", msg[0]);
  177. break;
  178. case EVENT_MSG_ID:
  179. printk(KERN_INFO"audpre: arm9 event\n");
  180. break;
  181. default:
  182. printk(KERN_ERR "audpre: unknown event %d\n", id);
  183. }
  184. }
  185. void audrec_dsp_event(void *data, unsigned id, size_t len,
  186. void (*getevent) (void *ptr, size_t len))
  187. {
  188. struct msm_audio *prtd = data;
  189. unsigned long flag;
  190. uint16_t msg[MAX_DATA_SIZE/2];
  191. if (len > MAX_DATA_SIZE) {
  192. printk(KERN_ERR"audrec: event/msg too large(%d bytes)\n", len);
  193. return;
  194. }
  195. getevent(msg, len);
  196. switch (id) {
  197. case AUDREC_MSG_CMD_CFG_DONE_MSG:
  198. if (msg[0] & AUDREC_MSG_CFG_DONE_TYPE_0_UPDATE) {
  199. if (msg[0] & AUDREC_MSG_CFG_DONE_TYPE_0_ENA)
  200. audrec_encoder_config(prtd);
  201. else
  202. prtd->running = 0;
  203. }
  204. break;
  205. case AUDREC_MSG_CMD_AREC_PARAM_CFG_DONE_MSG:{
  206. prtd->running = 1;
  207. break;
  208. }
  209. case AUDREC_MSG_FATAL_ERR_MSG:
  210. printk(KERN_ERR "audrec: ERROR %x\n", msg[0]);
  211. break;
  212. case AUDREC_MSG_PACKET_READY_MSG:
  213. alsa_get_dsp_frames(prtd);
  214. ++intcnt;
  215. if (prtd->channel_mode == 1) {
  216. spin_lock_irqsave(&the_locks.read_dsp_lock, flag);
  217. prtd->pcm_irq_pos += prtd->pcm_count;
  218. if (prtd->pcm_irq_pos >= prtd->pcm_size)
  219. prtd->pcm_irq_pos = 0;
  220. spin_unlock_irqrestore(&the_locks.read_dsp_lock, flag);
  221. if (prtd->ops->capture)
  222. prtd->ops->capture(prtd);
  223. } else if ((prtd->channel_mode == 0) && (intcnt % 2 == 0)) {
  224. spin_lock_irqsave(&the_locks.read_dsp_lock, flag);
  225. prtd->pcm_irq_pos += prtd->pcm_count;
  226. if (prtd->pcm_irq_pos >= prtd->pcm_size)
  227. prtd->pcm_irq_pos = 0;
  228. spin_unlock_irqrestore(&the_locks.read_dsp_lock, flag);
  229. if (prtd->ops->capture)
  230. prtd->ops->capture(prtd);
  231. }
  232. break;
  233. case EVENT_MSG_ID:
  234. printk(KERN_INFO"audrec: arm9 event\n");
  235. break;
  236. default:
  237. printk(KERN_ERR "audrec: unknown event %d\n", id);
  238. }
  239. }
  240. struct msm_adsp_ops aud_pre_adsp_ops = {
  241. .event = alsa_audpre_dsp_event,
  242. };
  243. struct msm_adsp_ops aud_rec_adsp_ops = {
  244. .event = audrec_dsp_event,
  245. };
  246. int alsa_adsp_configure(struct msm_audio *prtd)
  247. {
  248. int ret, i;
  249. if (prtd->dir == SNDRV_PCM_STREAM_PLAYBACK) {
  250. prtd->data = prtd->playback_substream->dma_buffer.area;
  251. prtd->phys = prtd->playback_substream->dma_buffer.addr;
  252. }
  253. if (prtd->dir == SNDRV_PCM_STREAM_CAPTURE) {
  254. prtd->data = prtd->capture_substream->dma_buffer.area;
  255. prtd->phys = prtd->capture_substream->dma_buffer.addr;
  256. }
  257. if (!prtd->data) {
  258. ret = -ENOMEM;
  259. goto err1;
  260. }
  261. ret = audmgr_open(&prtd->audmgr);
  262. if (ret)
  263. goto err2;
  264. if (prtd->dir == SNDRV_PCM_STREAM_PLAYBACK) {
  265. prtd->out_buffer_size = PLAYBACK_DMASZ;
  266. prtd->out_sample_rate = 44100;
  267. prtd->out_channel_mode = AUDPP_CMD_PCM_INTF_STEREO_V;
  268. prtd->out_weight = 100;
  269. prtd->out[0].data = prtd->data + 0;
  270. prtd->out[0].addr = prtd->phys + 0;
  271. prtd->out[0].size = BUFSZ;
  272. prtd->out[1].data = prtd->data + BUFSZ;
  273. prtd->out[1].addr = prtd->phys + BUFSZ;
  274. prtd->out[1].size = BUFSZ;
  275. }
  276. if (prtd->dir == SNDRV_PCM_STREAM_CAPTURE) {
  277. prtd->samp_rate = RPC_AUD_DEF_SAMPLE_RATE_44100;
  278. prtd->samp_rate_index = AUDREC_CMD_SAMP_RATE_INDX_44100;
  279. prtd->channel_mode = AUDREC_CMD_STEREO_MODE_STEREO;
  280. prtd->buffer_size = STEREO_DATA_SIZE;
  281. prtd->type = AUDREC_CMD_TYPE_0_INDEX_WAV;
  282. prtd->tx_agc_cfg.cmd_id = AUDPREPROC_CMD_CFG_AGC_PARAMS;
  283. prtd->ns_cfg.cmd_id = AUDPREPROC_CMD_CFG_NS_PARAMS;
  284. prtd->iir_cfg.cmd_id =
  285. AUDPREPROC_CMD_CFG_IIR_TUNING_FILTER_PARAMS;
  286. ret = msm_adsp_get("AUDPREPROCTASK",
  287. &prtd->audpre, &aud_pre_adsp_ops, prtd);
  288. if (ret)
  289. goto err3;
  290. ret = msm_adsp_get("AUDRECTASK",
  291. &prtd->audrec, &aud_rec_adsp_ops, prtd);
  292. if (ret) {
  293. msm_adsp_put(prtd->audpre);
  294. goto err3;
  295. }
  296. prtd->dsp_cnt = 0;
  297. prtd->in_head = 0;
  298. prtd->in_tail = 0;
  299. prtd->in_count = 0;
  300. for (i = 0; i < FRAME_NUM; i++) {
  301. prtd->in[i].size = 0;
  302. prtd->in[i].read = 0;
  303. }
  304. }
  305. return 0;
  306. err3:
  307. audmgr_close(&prtd->audmgr);
  308. err2:
  309. prtd->data = NULL;
  310. err1:
  311. return ret;
  312. }
  313. EXPORT_SYMBOL(alsa_adsp_configure);
  314. int alsa_audio_configure(struct msm_audio *prtd)
  315. {
  316. struct audmgr_config cfg;
  317. int rc;
  318. if (prtd->enabled)
  319. return 0;
  320. /* refuse to start if we're not ready with first buffer */
  321. if (!prtd->out[0].used)
  322. return -EIO;
  323. cfg.tx_rate = 0;
  324. cfg.rx_rate = RPC_AUD_DEF_SAMPLE_RATE_48000;
  325. cfg.def_method = RPC_AUD_DEF_METHOD_HOST_PCM;
  326. cfg.codec = RPC_AUD_DEF_CODEC_PCM;
  327. cfg.snd_method = RPC_SND_METHOD_MIDI;
  328. rc = audmgr_enable(&prtd->audmgr, &cfg);
  329. if (rc < 0)
  330. return rc;
  331. if (audpp_enable(AUDPP_ALSA_DECODER, alsa_dsp_event, prtd)) {
  332. printk(KERN_ERR "audio: audpp_enable() failed\n");
  333. audmgr_disable(&prtd->audmgr);
  334. return -ENODEV;
  335. }
  336. prtd->enabled = 1;
  337. return 0;
  338. }
  339. EXPORT_SYMBOL(alsa_audio_configure);
  340. ssize_t alsa_send_buffer(struct msm_audio *prtd, const char __user *buf,
  341. size_t count, loff_t *pos)
  342. {
  343. unsigned long flag;
  344. const char __user *start = buf;
  345. struct buffer *frame;
  346. size_t xfer;
  347. int rc = 0;
  348. mutex_lock(&the_locks.write_lock);
  349. while (count > 0) {
  350. frame = prtd->out + prtd->out_head;
  351. rc = wait_event_interruptible(the_locks.write_wait,
  352. (frame->used == 0)
  353. || (prtd->stopped));
  354. if (rc < 0)
  355. break;
  356. if (prtd->stopped) {
  357. rc = -EBUSY;
  358. break;
  359. }
  360. xfer = count > frame->size ? frame->size : count;
  361. if (copy_from_user(frame->data, buf, xfer)) {
  362. rc = -EFAULT;
  363. break;
  364. }
  365. frame->used = xfer;
  366. prtd->out_head ^= 1;
  367. count -= xfer;
  368. buf += xfer;
  369. spin_lock_irqsave(&the_locks.write_dsp_lock, flag);
  370. frame = prtd->out + prtd->out_tail;
  371. if (frame->used && prtd->out_needed) {
  372. alsa_dsp_send_buffer(prtd, prtd->out_tail,
  373. frame->used);
  374. prtd->out_tail ^= 1;
  375. prtd->out_needed--;
  376. }
  377. spin_unlock_irqrestore(&the_locks.write_dsp_lock, flag);
  378. }
  379. mutex_unlock(&the_locks.write_lock);
  380. if (buf > start)
  381. return buf - start;
  382. return rc;
  383. }
  384. EXPORT_SYMBOL(alsa_send_buffer);
  385. int alsa_audio_disable(struct msm_audio *prtd)
  386. {
  387. if (prtd->enabled) {
  388. mutex_lock(&the_locks.lock);
  389. prtd->enabled = 0;
  390. audio_dsp_out_enable(prtd, 0);
  391. wake_up(&the_locks.write_wait);
  392. audpp_disable(AUDPP_ALSA_DECODER, prtd);
  393. audmgr_disable(&prtd->audmgr);
  394. prtd->out_needed = 0;
  395. mutex_unlock(&the_locks.lock);
  396. }
  397. return 0;
  398. }
  399. EXPORT_SYMBOL(alsa_audio_disable);
  400. int alsa_audrec_disable(struct msm_audio *prtd)
  401. {
  402. if (prtd->enabled) {
  403. mutex_lock(&the_locks.lock);
  404. prtd->enabled = 0;
  405. alsa_rec_dsp_enable(prtd, 0);
  406. wake_up(&the_locks.read_wait);
  407. msm_adsp_disable(prtd->audpre);
  408. msm_adsp_disable(prtd->audrec);
  409. audmgr_disable(&prtd->audmgr);
  410. prtd->out_needed = 0;
  411. prtd->opened = 0;
  412. mutex_unlock(&the_locks.lock);
  413. }
  414. return 0;
  415. }
  416. EXPORT_SYMBOL(alsa_audrec_disable);
  417. static int audio_dsp_read_buffer(struct msm_audio *prtd, uint32_t read_cnt)
  418. {
  419. audrec_cmd_packet_ext_ptr cmd;
  420. memset(&cmd, 0, sizeof(cmd));
  421. cmd.cmd_id = AUDREC_CMD_PACKET_EXT_PTR;
  422. /* Both WAV and AAC use AUDREC_CMD_TYPE_0 */
  423. cmd.type = AUDREC_CMD_TYPE_0;
  424. cmd.curr_rec_count_msw = read_cnt >> 16;
  425. cmd.curr_rec_count_lsw = read_cnt;
  426. return audio_send_queue_recbs(prtd, &cmd, sizeof(cmd));
  427. }
  428. int audrec_encoder_config(struct msm_audio *prtd)
  429. {
  430. audrec_cmd_arec0param_cfg cmd;
  431. uint16_t *data = (void *)prtd->data;
  432. unsigned n;
  433. memset(&cmd, 0, sizeof(cmd));
  434. cmd.cmd_id = AUDREC_CMD_AREC0PARAM_CFG;
  435. cmd.ptr_to_extpkt_buffer_msw = prtd->phys >> 16;
  436. cmd.ptr_to_extpkt_buffer_lsw = prtd->phys;
  437. cmd.buf_len = FRAME_NUM; /* Both WAV and AAC use 8 frames */
  438. cmd.samp_rate_index = prtd->samp_rate_index;
  439. /* 0 for mono, 1 for stereo */
  440. cmd.stereo_mode = prtd->channel_mode;
  441. cmd.rec_quality = 0x1C00;
  442. /* prepare buffer pointers:
  443. * Mono: 1024 samples + 4 halfword header
  444. * Stereo: 2048 samples + 4 halfword header
  445. */
  446. for (n = 0; n < FRAME_NUM; n++) {
  447. prtd->in[n].data = data + 4;
  448. data += (4 + (prtd->channel_mode ? 2048 : 1024));
  449. }
  450. return audio_send_queue_rec(prtd, &cmd, sizeof(cmd));
  451. }
  452. int audio_dsp_out_enable(struct msm_audio *prtd, int yes)
  453. {
  454. audpp_cmd_pcm_intf cmd;
  455. memset(&cmd, 0, sizeof(cmd));
  456. cmd.cmd_id = AUDPP_CMD_PCM_INTF_2;
  457. cmd.object_num = AUDPP_CMD_PCM_INTF_OBJECT_NUM;
  458. cmd.config = AUDPP_CMD_PCM_INTF_CONFIG_CMD_V;
  459. cmd.intf_type = AUDPP_CMD_PCM_INTF_RX_ENA_ARMTODSP_V;
  460. if (yes) {
  461. cmd.write_buf1LSW = prtd->out[0].addr;
  462. cmd.write_buf1MSW = prtd->out[0].addr >> 16;
  463. cmd.write_buf1_len = 0;
  464. cmd.write_buf2LSW = prtd->out[1].addr;
  465. cmd.write_buf2MSW = prtd->out[1].addr >> 16;
  466. cmd.write_buf2_len = prtd->out[1].used;
  467. cmd.arm_to_rx_flag = AUDPP_CMD_PCM_INTF_ENA_V;
  468. cmd.weight_decoder_to_rx = prtd->out_weight;
  469. cmd.weight_arm_to_rx = 1;
  470. cmd.partition_number_arm_to_dsp = 0;
  471. cmd.sample_rate = prtd->out_sample_rate;
  472. cmd.channel_mode = prtd->out_channel_mode;
  473. }
  474. return audpp_send_queue2(&cmd, sizeof(cmd));
  475. }
  476. int alsa_buffer_read(struct msm_audio *prtd, void __user *buf,
  477. size_t count, loff_t *pos)
  478. {
  479. unsigned long flag;
  480. void *data;
  481. uint32_t index;
  482. uint32_t size;
  483. int rc = 0;
  484. mutex_lock(&the_locks.read_lock);
  485. while (count > 0) {
  486. rc = wait_event_interruptible(the_locks.read_wait,
  487. (prtd->in_count > 0)
  488. || prtd->stopped);
  489. if (rc < 0)
  490. break;
  491. if (prtd->stopped) {
  492. rc = -EBUSY;
  493. break;
  494. }
  495. index = prtd->in_tail;
  496. data = (uint8_t *) prtd->in[index].data;
  497. size = prtd->in[index].size;
  498. if (count >= size) {
  499. if (copy_to_user(buf, data, size)) {
  500. rc = -EFAULT;
  501. break;
  502. }
  503. spin_lock_irqsave(&the_locks.read_dsp_lock, flag);
  504. if (index != prtd->in_tail) {
  505. /* overrun: data is invalid, we need to retry */
  506. spin_unlock_irqrestore(&the_locks.read_dsp_lock,
  507. flag);
  508. continue;
  509. }
  510. prtd->in[index].size = 0;
  511. prtd->in_tail = (prtd->in_tail + 1) & (FRAME_NUM - 1);
  512. prtd->in_count--;
  513. spin_unlock_irqrestore(&the_locks.read_dsp_lock, flag);
  514. count -= size;
  515. buf += size;
  516. } else {
  517. break;
  518. }
  519. }
  520. mutex_unlock(&the_locks.read_lock);
  521. return rc;
  522. }
  523. EXPORT_SYMBOL(alsa_buffer_read);
  524. int alsa_dsp_send_buffer(struct msm_audio *prtd,
  525. unsigned idx, unsigned len)
  526. {
  527. audpp_cmd_pcm_intf_send_buffer cmd;
  528. cmd.cmd_id = AUDPP_CMD_PCM_INTF_2;
  529. cmd.host_pcm_object = AUDPP_CMD_PCM_INTF_OBJECT_NUM;
  530. cmd.config = AUDPP_CMD_PCM_INTF_BUFFER_CMD_V;
  531. cmd.intf_type = AUDPP_CMD_PCM_INTF_RX_ENA_ARMTODSP_V;
  532. cmd.dsp_to_arm_buf_id = 0;
  533. cmd.arm_to_dsp_buf_id = idx + 1;
  534. cmd.arm_to_dsp_buf_len = len;
  535. return audpp_send_queue2(&cmd, sizeof(cmd));
  536. }
  537. int alsa_rec_dsp_enable(struct msm_audio *prtd, int enable)
  538. {
  539. audrec_cmd_cfg cmd;
  540. memset(&cmd, 0, sizeof(cmd));
  541. cmd.cmd_id = AUDREC_CMD_CFG;
  542. cmd.type_0 = enable ? AUDREC_CMD_TYPE_0_ENA : AUDREC_CMD_TYPE_0_DIS;
  543. cmd.type_0 |= (AUDREC_CMD_TYPE_0_UPDATE | prtd->type);
  544. cmd.type_1 = 0;
  545. return audio_send_queue_rec(prtd, &cmd, sizeof(cmd));
  546. }
  547. EXPORT_SYMBOL(alsa_rec_dsp_enable);
  548. void alsa_get_dsp_frames(struct msm_audio *prtd)
  549. {
  550. struct audio_frame *frame;
  551. uint32_t index = 0;
  552. unsigned long flag;
  553. if (prtd->type == AUDREC_CMD_TYPE_0_INDEX_WAV) {
  554. index = prtd->in_head;
  555. frame =
  556. (void *)(((char *)prtd->in[index].data) - sizeof(*frame));
  557. spin_lock_irqsave(&the_locks.read_dsp_lock, flag);
  558. prtd->in[index].size = frame->bytes;
  559. prtd->in_head = (prtd->in_head + 1) & (FRAME_NUM - 1);
  560. /* If overflow, move the tail index foward. */
  561. if (prtd->in_head == prtd->in_tail)
  562. prtd->in_tail = (prtd->in_tail + 1) & (FRAME_NUM - 1);
  563. else
  564. prtd->in_count++;
  565. audio_dsp_read_buffer(prtd, prtd->dsp_cnt++);
  566. spin_unlock_irqrestore(&the_locks.read_dsp_lock, flag);
  567. wake_up(&the_locks.read_wait);
  568. } else {
  569. /* TODO AAC not supported yet. */
  570. }
  571. }
  572. EXPORT_SYMBOL(alsa_get_dsp_frames);