msm-voip.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611
  1. /* Copyright (c) 2011, The Linux Foundation. All rights reserved.
  2. *
  3. * All source code in this file is licensed under the following license except
  4. * where indicated.
  5. *
  6. * This program is free software; you can redistribute it and/or modify it
  7. * under the terms of the GNU General Public License version 2 as published
  8. * by the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. *
  14. * See the GNU General Public License for more details.
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, you can find it at http://www.fsf.org.
  17. */
  18. #include <linux/init.h>
  19. #include <linux/err.h>
  20. #include <linux/module.h>
  21. #include <linux/moduleparam.h>
  22. #include <linux/time.h>
  23. #include <linux/wait.h>
  24. #include <linux/platform_device.h>
  25. #include <linux/mutex.h>
  26. #include <linux/uaccess.h>
  27. #include <linux/wakelock.h>
  28. #include <linux/dma-mapping.h>
  29. #include <sound/core.h>
  30. #include <sound/soc.h>
  31. #include <sound/pcm.h>
  32. #include <sound/initval.h>
  33. #include <sound/control.h>
  34. #include <sound/q6asm.h>
  35. #include <sound/apr_audio.h>
  36. #include <mach/msm_rpcrouter.h>
  37. #include <mach/qdsp6v2/q6voice.h>
  38. #include <mach/qdsp6v2/audio_dev_ctl.h>
  39. #include "msm_audio_mvs.h"
  40. static struct audio_voip_info_type audio_voip_info;
  41. static void audio_mvs_process_ul_pkt(uint8_t *voc_pkt,
  42. uint32_t pkt_len,
  43. void *private_data);
  44. static void audio_mvs_process_dl_pkt(uint8_t *voc_pkt,
  45. uint32_t *pkt_len,
  46. void *private_data);
  47. struct msm_audio_mvs_frame {
  48. uint32_t frame_type;
  49. uint32_t len;
  50. uint8_t voc_pkt[MVS_MAX_VOC_PKT_SIZE];
  51. };
  52. struct audio_mvs_buf_node {
  53. struct list_head list;
  54. struct msm_audio_mvs_frame frame;
  55. };
  56. static struct snd_pcm_hardware msm_pcm_hardware = {
  57. .info = SNDRV_PCM_INFO_INTERLEAVED,
  58. .formats = SNDRV_PCM_FMTBIT_S16_LE,
  59. .rates = (SNDRV_PCM_RATE_8000),
  60. .rate_min = 8000,
  61. .rate_max = 8000,
  62. .channels_min = 1,
  63. .channels_max = 2,
  64. .buffer_bytes_max = MVS_MAX_VOC_PKT_SIZE * VOIP_MAX_Q_LEN,
  65. .period_bytes_min = MVS_MAX_VOC_PKT_SIZE,
  66. .period_bytes_max = MVS_MAX_VOC_PKT_SIZE,
  67. .periods_min = VOIP_MAX_Q_LEN,
  68. .periods_max = VOIP_MAX_Q_LEN,
  69. .fifo_size = 0,
  70. };
  71. static int msm_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
  72. {
  73. struct audio_voip_info_type *audio = &audio_voip_info;
  74. pr_debug("%s\n", __func__);
  75. switch (cmd) {
  76. case SNDRV_PCM_TRIGGER_START:
  77. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  78. audio->playback_start = 1;
  79. else
  80. audio->capture_start = 1;
  81. break;
  82. case SNDRV_PCM_TRIGGER_STOP:
  83. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  84. audio->playback_start = 0;
  85. else
  86. audio->capture_start = 0;
  87. break;
  88. default:
  89. break;
  90. }
  91. return 0;
  92. }
  93. static int msm_pcm_close(struct snd_pcm_substream *substream)
  94. {
  95. int rc = 0;
  96. struct audio_voip_info_type *audio = &audio_voip_info;
  97. struct audio_mvs_release_msg release_msg;
  98. pr_debug("%s\n", __func__);
  99. memset(&release_msg, 0, sizeof(release_msg));
  100. mutex_lock(&audio->lock);
  101. audio->instance--;
  102. wake_up(&audio->out_wait);
  103. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  104. audio->playback_state = AUDIO_MVS_CLOSED;
  105. else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
  106. audio->capture_state = AUDIO_MVS_CLOSED;
  107. if (!audio->instance) {
  108. /* Release MVS. */
  109. release_msg.client_id = cpu_to_be32(MVS_CLIENT_ID_VOIP);
  110. /* Derigstering the callbacks with voice driver */
  111. voice_register_mvs_cb(NULL, NULL, audio);
  112. } else if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  113. voice_register_mvs_cb(audio_mvs_process_ul_pkt,
  114. NULL, audio);
  115. } else {
  116. voice_register_mvs_cb(NULL, audio_mvs_process_dl_pkt,
  117. audio);
  118. }
  119. mutex_unlock(&audio->lock);
  120. wake_unlock(&audio->suspend_lock);
  121. pm_qos_update_request(&audio->pm_qos_req, PM_QOS_DEFAULT_VALUE);
  122. /* Release the IO buffers. */
  123. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  124. audio->in_write = 0;
  125. audio->in_read = 0;
  126. memset(audio->in[0].voc_pkt, 0,
  127. MVS_MAX_VOC_PKT_SIZE * VOIP_MAX_Q_LEN);
  128. audio->playback_substream = NULL;
  129. } else {
  130. audio->out_write = 0;
  131. audio->out_read = 0;
  132. memset(audio->out[0].voc_pkt, 0,
  133. MVS_MAX_VOC_PKT_SIZE * VOIP_MAX_Q_LEN);
  134. audio->capture_substream = NULL;
  135. }
  136. return rc;
  137. }
  138. static int msm_pcm_open(struct snd_pcm_substream *substream)
  139. {
  140. int ret = 0;
  141. struct snd_pcm_runtime *runtime = substream->runtime;
  142. struct audio_voip_info_type *audio = &audio_voip_info;
  143. pr_debug("%s\n", __func__);
  144. mutex_lock(&audio->lock);
  145. if (audio->playback_substream == NULL ||
  146. audio->capture_substream == NULL) {
  147. if (substream->stream ==
  148. SNDRV_PCM_STREAM_PLAYBACK) {
  149. audio->playback_substream = substream;
  150. runtime->hw = msm_pcm_hardware;
  151. audio_voip_info.in_read = 0;
  152. audio_voip_info.in_write = 0;
  153. if (audio->playback_state < AUDIO_MVS_OPENED)
  154. audio->playback_state = AUDIO_MVS_OPENED;
  155. } else if (substream->stream ==
  156. SNDRV_PCM_STREAM_CAPTURE) {
  157. audio->capture_substream = substream;
  158. runtime->hw = msm_pcm_hardware;
  159. audio_voip_info.out_read = 0;
  160. audio_voip_info.out_write = 0;
  161. if (audio->capture_state < AUDIO_MVS_OPENED)
  162. audio->capture_state = AUDIO_MVS_OPENED;
  163. }
  164. } else {
  165. ret = -EPERM;
  166. goto err;
  167. }
  168. ret = snd_pcm_hw_constraint_integer(runtime,
  169. SNDRV_PCM_HW_PARAM_PERIODS);
  170. if (ret < 0) {
  171. pr_debug("%s:snd_pcm_hw_constraint_integer failed\n", __func__);
  172. goto err;
  173. }
  174. audio->instance++;
  175. err:
  176. mutex_unlock(&audio->lock);
  177. return ret;
  178. }
  179. static int msm_pcm_playback_copy(struct snd_pcm_substream *substream, int a,
  180. snd_pcm_uframes_t hwoff, void __user *buf,
  181. snd_pcm_uframes_t frames)
  182. {
  183. int rc = 0;
  184. int count = 0;
  185. struct snd_pcm_runtime *runtime = substream->runtime;
  186. struct audio_voip_info_type *audio = &audio_voip_info;
  187. uint32_t index;
  188. pr_debug("%s\n", __func__);
  189. rc = wait_event_timeout(audio->in_wait,
  190. (audio->in_write - audio->in_read <= VOIP_MAX_Q_LEN-1),
  191. 1 * HZ);
  192. if (rc < 0) {
  193. pr_debug("%s: write was interrupted\n", __func__);
  194. return -ERESTARTSYS;
  195. }
  196. if (audio->playback_state == AUDIO_MVS_ENABLED) {
  197. index = audio->in_write % VOIP_MAX_Q_LEN;
  198. count = frames_to_bytes(runtime, frames);
  199. if (count == MVS_MAX_VOC_PKT_SIZE) {
  200. pr_debug("%s:write index = %d\n", __func__, index);
  201. rc = copy_from_user(audio->in[index].voc_pkt, buf,
  202. count);
  203. if (!rc) {
  204. audio->in[index].len = count;
  205. audio->in_write++;
  206. } else {
  207. pr_debug("%s:Copy from user returned %d\n",
  208. __func__, rc);
  209. rc = -EFAULT;
  210. }
  211. } else
  212. rc = -ENOMEM;
  213. } else {
  214. pr_debug("%s:Write performed in invalid state %d\n",
  215. __func__, audio->playback_state);
  216. rc = -EINVAL;
  217. }
  218. return rc;
  219. }
  220. static int msm_pcm_capture_copy(struct snd_pcm_substream *substream,
  221. int channel, snd_pcm_uframes_t hwoff,
  222. void __user *buf, snd_pcm_uframes_t frames)
  223. {
  224. int rc = 0;
  225. int count = 0;
  226. struct snd_pcm_runtime *runtime = substream->runtime;
  227. struct audio_voip_info_type *audio = &audio_voip_info;
  228. uint32_t index = 0;
  229. pr_debug("%s\n", __func__);
  230. /* Ensure the driver has been enabled. */
  231. if (audio->capture_state != AUDIO_MVS_ENABLED) {
  232. pr_debug("%s:Read performed in invalid state %d\n",
  233. __func__, audio->capture_state);
  234. return -EPERM;
  235. }
  236. rc = wait_event_timeout(audio->out_wait,
  237. ((audio->out_read < audio->out_write) ||
  238. (audio->capture_state == AUDIO_MVS_CLOSING) ||
  239. (audio->capture_state == AUDIO_MVS_CLOSED)),
  240. 1 * HZ);
  241. if (rc < 0) {
  242. pr_debug("%s: Read was interrupted\n", __func__);
  243. return -ERESTARTSYS;
  244. }
  245. if (audio->capture_state == AUDIO_MVS_CLOSING
  246. || audio->capture_state == AUDIO_MVS_CLOSED) {
  247. pr_debug("%s:EBUSY STATE\n", __func__);
  248. rc = -EBUSY;
  249. } else {
  250. count = frames_to_bytes(runtime, frames);
  251. index = audio->out_read % VOIP_MAX_Q_LEN;
  252. pr_debug("%s:index=%d\n", __func__, index);
  253. if (audio->out[index].len <= count) {
  254. rc = copy_to_user(buf,
  255. audio->out[index].voc_pkt,
  256. audio->out[index].len);
  257. if (rc) {
  258. pr_debug("%s:Copy to user %d\n",
  259. __func__, rc);
  260. rc = -EFAULT;
  261. } else
  262. audio->out_read++;
  263. } else {
  264. pr_debug("%s:returning ENOMEM\n", __func__);
  265. rc = -ENOMEM;
  266. }
  267. }
  268. return rc;
  269. }
  270. static int msm_pcm_copy(struct snd_pcm_substream *substream, int a,
  271. snd_pcm_uframes_t hwoff, void __user *buf,
  272. snd_pcm_uframes_t frames)
  273. {
  274. int ret = 0;
  275. pr_debug("%s\n", __func__);
  276. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  277. ret = msm_pcm_playback_copy(substream, a, hwoff, buf, frames);
  278. else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
  279. ret = msm_pcm_capture_copy(substream, a, hwoff, buf, frames);
  280. return ret;
  281. }
  282. /* Capture path */
  283. static void audio_mvs_process_ul_pkt(uint8_t *voc_pkt,
  284. uint32_t pkt_len,
  285. void *private_data)
  286. {
  287. struct audio_voip_info_type *audio = private_data;
  288. uint32_t index;
  289. static int i;
  290. pr_debug("%s\n", __func__);
  291. if (audio->capture_substream == NULL)
  292. return;
  293. index = audio->out_write % VOIP_MAX_Q_LEN;
  294. memcpy(audio->out[index].voc_pkt, voc_pkt, pkt_len);
  295. audio->out[index].len = pkt_len;
  296. audio->out_write++;
  297. wake_up(&audio->out_wait);
  298. i++;
  299. if (audio->capture_start) {
  300. audio->pcm_capture_irq_pos += audio->pcm_count;
  301. if (!(i % 2))
  302. snd_pcm_period_elapsed(audio->capture_substream);
  303. }
  304. }
  305. /* Playback path */
  306. static void audio_mvs_process_dl_pkt(uint8_t *voc_pkt,
  307. uint32_t *pkt_len,
  308. void *private_data)
  309. {
  310. struct audio_voip_info_type *audio = private_data;
  311. uint32_t index;
  312. static int i;
  313. pr_debug("%s\n", __func__);
  314. if (audio->playback_substream == NULL)
  315. return;
  316. if ((audio->in_write - audio->in_read >= 0)
  317. && (audio->playback_start)) {
  318. index = audio->in_read % VOIP_MAX_Q_LEN;
  319. *pkt_len = audio->pcm_count;
  320. memcpy(voc_pkt, audio->in[index].voc_pkt, *pkt_len);
  321. audio->in_read++;
  322. wake_up(&audio->in_wait);
  323. i++;
  324. audio->pcm_playback_irq_pos += audio->pcm_count;
  325. if (!(i%2))
  326. snd_pcm_period_elapsed(audio->playback_substream);
  327. pr_debug("%s:read_index=%d\n", __func__, index);
  328. }
  329. }
  330. static int msm_pcm_prepare(struct snd_pcm_substream *substream)
  331. {
  332. int rc = 0;
  333. struct audio_voip_info_type *prtd = &audio_voip_info;
  334. pr_debug("%s\n", __func__);
  335. prtd->pcm_playback_size = snd_pcm_lib_buffer_bytes(substream);
  336. prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
  337. pr_debug("%s:prtd->pcm_playback_size:%d\n",
  338. __func__, prtd->pcm_playback_size);
  339. pr_debug("%s:prtd->pcm_count:%d\n", __func__, prtd->pcm_count);
  340. mutex_lock(&prtd->prepare_lock);
  341. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  342. if (prtd->playback_state == AUDIO_MVS_ENABLED)
  343. goto enabled;
  344. } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
  345. if (prtd->capture_state == AUDIO_MVS_ENABLED)
  346. goto enabled;
  347. }
  348. pr_debug("%s:Register cbs with voice driver check audio_mvs_driver\n",
  349. __func__);
  350. if (prtd->instance == 2) {
  351. voice_register_mvs_cb(audio_mvs_process_ul_pkt,
  352. audio_mvs_process_dl_pkt,
  353. prtd);
  354. } else {
  355. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  356. voice_register_mvs_cb(NULL,
  357. audio_mvs_process_dl_pkt,
  358. prtd);
  359. } else {
  360. voice_register_mvs_cb(audio_mvs_process_ul_pkt,
  361. NULL,
  362. prtd);
  363. }
  364. }
  365. enabled:
  366. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  367. prtd->playback_state = AUDIO_MVS_ENABLED;
  368. prtd->pcm_playback_irq_pos = 0;
  369. prtd->pcm_playback_buf_pos = 0;
  370. /* rate and channels are sent to audio driver */
  371. } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
  372. prtd->capture_state = AUDIO_MVS_ENABLED;
  373. prtd->pcm_capture_size = snd_pcm_lib_buffer_bytes(substream);
  374. prtd->pcm_capture_count = snd_pcm_lib_period_bytes(substream);
  375. prtd->pcm_capture_irq_pos = 0;
  376. prtd->pcm_capture_buf_pos = 0;
  377. }
  378. mutex_unlock(&prtd->prepare_lock);
  379. return rc;
  380. }
  381. static snd_pcm_uframes_t
  382. msm_pcm_playback_pointer(struct snd_pcm_substream *substream)
  383. {
  384. struct snd_pcm_runtime *runtime = substream->runtime;
  385. struct audio_voip_info_type *audio = &audio_voip_info;
  386. if (audio->pcm_playback_irq_pos >= audio->pcm_playback_size)
  387. audio->pcm_playback_irq_pos = 0;
  388. return bytes_to_frames(runtime, (audio->pcm_playback_irq_pos));
  389. }
  390. static snd_pcm_uframes_t
  391. msm_pcm_capture_pointer(struct snd_pcm_substream *substream)
  392. {
  393. struct snd_pcm_runtime *runtime = substream->runtime;
  394. struct audio_voip_info_type *audio = &audio_voip_info;
  395. if (audio->pcm_capture_irq_pos >= audio->pcm_capture_size)
  396. audio->pcm_capture_irq_pos = 0;
  397. return bytes_to_frames(runtime, (audio->pcm_capture_irq_pos));
  398. }
  399. static snd_pcm_uframes_t msm_pcm_pointer(struct snd_pcm_substream *substream)
  400. {
  401. snd_pcm_uframes_t ret = 0;
  402. pr_debug("%s\n", __func__);
  403. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  404. ret = msm_pcm_playback_pointer(substream);
  405. else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
  406. ret = msm_pcm_capture_pointer(substream);
  407. return ret;
  408. }
  409. static struct snd_pcm_ops msm_mvs_pcm_ops = {
  410. .open = msm_pcm_open,
  411. .copy = msm_pcm_copy,
  412. .close = msm_pcm_close,
  413. .ioctl = snd_pcm_lib_ioctl,
  414. .prepare = msm_pcm_prepare,
  415. .trigger = msm_pcm_trigger,
  416. .pointer = msm_pcm_pointer,
  417. };
  418. static int msm_pcm_new(struct snd_soc_pcm_runtime *rtd)
  419. {
  420. int i, ret, offset = 0;
  421. struct snd_pcm_substream *substream = NULL;
  422. struct snd_dma_buffer *dma_buffer = NULL;
  423. struct snd_card *card = rtd->card->snd_card;
  424. struct snd_pcm *pcm = rtd->pcm;
  425. ret = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_PLAYBACK, 1);
  426. if (ret)
  427. return ret;
  428. ret = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_CAPTURE, 1);
  429. if (ret)
  430. return ret;
  431. snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &msm_mvs_pcm_ops);
  432. snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &msm_mvs_pcm_ops);
  433. if (!card->dev->coherent_dma_mask)
  434. card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
  435. substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
  436. if (!substream)
  437. return -ENOMEM;
  438. dma_buffer = &substream->dma_buffer;
  439. dma_buffer->dev.type = SNDRV_DMA_TYPE_DEV;
  440. dma_buffer->dev.dev = card->dev;
  441. dma_buffer->private_data = NULL;
  442. dma_buffer->area = dma_alloc_coherent(card->dev,
  443. (MVS_MAX_VOC_PKT_SIZE * VOIP_MAX_Q_LEN),
  444. &dma_buffer->addr, GFP_KERNEL);
  445. if (!dma_buffer->area) {
  446. pr_err("%s:MSM VOIP dma_alloc failed\n", __func__);
  447. return -ENOMEM;
  448. }
  449. dma_buffer->bytes = MVS_MAX_VOC_PKT_SIZE * VOIP_MAX_Q_LEN;
  450. memset(dma_buffer->area, 0, MVS_MAX_VOC_PKT_SIZE * VOIP_MAX_Q_LEN);
  451. audio_voip_info.in_read = 0;
  452. audio_voip_info.in_write = 0;
  453. audio_voip_info.out_read = 0;
  454. audio_voip_info.out_write = 0;
  455. for (i = 0; i < VOIP_MAX_Q_LEN; i++) {
  456. audio_voip_info.in[i].voc_pkt =
  457. dma_buffer->area + offset;
  458. offset = offset + MVS_MAX_VOC_PKT_SIZE;
  459. }
  460. substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
  461. if (!substream)
  462. return -ENOMEM;
  463. dma_buffer = &substream->dma_buffer;
  464. dma_buffer->dev.type = SNDRV_DMA_TYPE_DEV;
  465. dma_buffer->dev.dev = card->dev;
  466. dma_buffer->private_data = NULL;
  467. dma_buffer->area = dma_alloc_coherent(card->dev,
  468. (MVS_MAX_VOC_PKT_SIZE * VOIP_MAX_Q_LEN),
  469. &dma_buffer->addr, GFP_KERNEL);
  470. if (!dma_buffer->area) {
  471. pr_err("%s:MSM VOIP dma_alloc failed\n", __func__);
  472. return -ENOMEM;
  473. }
  474. memset(dma_buffer->area, 0, MVS_MAX_VOC_PKT_SIZE * VOIP_MAX_Q_LEN);
  475. dma_buffer->bytes = MVS_MAX_VOC_PKT_SIZE * VOIP_MAX_Q_LEN;
  476. for (i = 0; i < VOIP_MAX_Q_LEN; i++) {
  477. audio_voip_info.out[i].voc_pkt =
  478. dma_buffer->area + offset;
  479. offset = offset + MVS_MAX_VOC_PKT_SIZE;
  480. }
  481. audio_voip_info.playback_substream = NULL;
  482. audio_voip_info.capture_substream = NULL;
  483. return 0;
  484. }
  485. static void msm_pcm_free_buffers(struct snd_pcm *pcm)
  486. {
  487. struct snd_pcm_substream *substream;
  488. struct snd_dma_buffer *buf;
  489. int stream;
  490. for (stream = 0; stream < 2; stream++) {
  491. substream = pcm->streams[stream].substream;
  492. if (!substream)
  493. continue;
  494. buf = &substream->dma_buffer;
  495. if (!buf->area)
  496. continue;
  497. dma_free_coherent(pcm->card->dev, buf->bytes,
  498. buf->area, buf->addr);
  499. buf->area = NULL;
  500. }
  501. }
  502. struct snd_soc_platform_driver msm_mvs_soc_platform = {
  503. .ops = &msm_mvs_pcm_ops,
  504. .pcm_new = msm_pcm_new,
  505. .pcm_free = msm_pcm_free_buffers,
  506. };
  507. EXPORT_SYMBOL(msm_mvs_soc_platform);
  508. static __devinit int msm_pcm_probe(struct platform_device *pdev)
  509. {
  510. dev_info(&pdev->dev, "%s: dev name %s\n", __func__, dev_name(&pdev->dev));
  511. return snd_soc_register_platform(&pdev->dev,
  512. &msm_mvs_soc_platform);
  513. }
  514. static int msm_pcm_remove(struct platform_device *pdev)
  515. {
  516. snd_soc_unregister_platform(&pdev->dev);
  517. return 0;
  518. }
  519. static struct platform_driver msm_pcm_driver = {
  520. .driver = {
  521. .name = "msm-mvs-audio",
  522. .owner = THIS_MODULE,
  523. },
  524. .probe = msm_pcm_probe,
  525. .remove = __devexit_p(msm_pcm_remove),
  526. };
  527. static int __init msm_mvs_soc_platform_init(void)
  528. {
  529. memset(&audio_voip_info, 0, sizeof(audio_voip_info));
  530. mutex_init(&audio_voip_info.lock);
  531. mutex_init(&audio_voip_info.prepare_lock);
  532. init_waitqueue_head(&audio_voip_info.out_wait);
  533. init_waitqueue_head(&audio_voip_info.in_wait);
  534. wake_lock_init(&audio_voip_info.suspend_lock, WAKE_LOCK_SUSPEND,
  535. "audio_mvs_suspend");
  536. pm_qos_add_request(&audio_voip_info.pm_qos_req, PM_QOS_CPU_DMA_LATENCY,
  537. PM_QOS_DEFAULT_VALUE);
  538. return platform_driver_register(&msm_pcm_driver);
  539. }
  540. module_init(msm_mvs_soc_platform_init);
  541. static void __exit msm_mvs_soc_platform_exit(void)
  542. {
  543. platform_driver_unregister(&msm_pcm_driver);
  544. }
  545. module_exit(msm_mvs_soc_platform_exit);
  546. MODULE_DESCRIPTION("MVS PCM module platform driver");
  547. MODULE_LICENSE("GPL v2");