msm7kv2-pcm.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775
  1. /* Copyright (c) 2008-2010, 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 <sound/core.h>
  26. #include <sound/soc.h>
  27. #include <sound/soc-dapm.h>
  28. #include <sound/pcm.h>
  29. #include <sound/initval.h>
  30. #include <sound/control.h>
  31. #include <asm/dma.h>
  32. #include <linux/dma-mapping.h>
  33. #include <linux/slab.h>
  34. #include "msm7kv2-pcm.h"
  35. #include <mach/qdsp5v2/audio_dev_ctl.h>
  36. #include <mach/debug_mm.h>
  37. #define HOSTPCM_STREAM_ID 5
  38. struct snd_msm {
  39. struct snd_card *card;
  40. struct snd_pcm *pcm;
  41. };
  42. int copy_count;
  43. static struct snd_pcm_hardware msm_pcm_playback_hardware = {
  44. .info = SNDRV_PCM_INFO_MMAP |
  45. SNDRV_PCM_INFO_MMAP_VALID |
  46. SNDRV_PCM_INFO_INTERLEAVED,
  47. .formats = USE_FORMATS,
  48. .rates = USE_RATE,
  49. .rate_min = USE_RATE_MIN,
  50. .rate_max = 48000,
  51. .channels_min = 1,
  52. .channels_max = 2,
  53. .buffer_bytes_max = MAX_BUFFER_PLAYBACK_SIZE,
  54. .period_bytes_min = BUFSZ,
  55. .period_bytes_max = BUFSZ,
  56. .periods_min = 2,
  57. .periods_max = 2,
  58. .fifo_size = 0,
  59. };
  60. static struct snd_pcm_hardware msm_pcm_capture_hardware = {
  61. .info = SNDRV_PCM_INFO_INTERLEAVED,
  62. .formats = USE_FORMATS,
  63. .rates = USE_RATE,
  64. .rate_min = 8000,
  65. .rate_max = 48000,
  66. .channels_min = 1,
  67. .channels_max = 2,
  68. .buffer_bytes_max = MAX_BUFFER_CAPTURE_SIZE,
  69. .period_bytes_min = 4096,
  70. .period_bytes_max = 4096,
  71. .periods_min = 4,
  72. .periods_max = 4,
  73. .fifo_size = 0,
  74. };
  75. /* Conventional and unconventional sample rate supported */
  76. static unsigned int supported_sample_rates[] = {
  77. 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
  78. };
  79. static struct snd_pcm_hw_constraint_list constraints_sample_rates = {
  80. .count = ARRAY_SIZE(supported_sample_rates),
  81. .list = supported_sample_rates,
  82. .mask = 0,
  83. };
  84. static void alsa_out_listener(u32 evt_id, union auddev_evt_data *evt_payload,
  85. void *private_data)
  86. {
  87. struct msm_audio *prtd = (struct msm_audio *) private_data;
  88. MM_DBG("evt_id = 0x%8x\n", evt_id);
  89. switch (evt_id) {
  90. case AUDDEV_EVT_DEV_RDY:
  91. MM_DBG("AUDDEV_EVT_DEV_RDY\n");
  92. prtd->source |= (0x1 << evt_payload->routing_id);
  93. if (prtd->running == 1 && prtd->enabled == 1)
  94. audpp_route_stream(prtd->session_id, prtd->source);
  95. break;
  96. case AUDDEV_EVT_DEV_RLS:
  97. MM_DBG("AUDDEV_EVT_DEV_RLS\n");
  98. prtd->source &= ~(0x1 << evt_payload->routing_id);
  99. if (prtd->running == 1 && prtd->enabled == 1)
  100. audpp_route_stream(prtd->session_id, prtd->source);
  101. break;
  102. case AUDDEV_EVT_STREAM_VOL_CHG:
  103. prtd->vol_pan.volume = evt_payload->session_vol;
  104. MM_DBG("AUDDEV_EVT_STREAM_VOL_CHG, stream vol %d\n",
  105. prtd->vol_pan.volume);
  106. if (prtd->running)
  107. audpp_set_volume_and_pan(prtd->session_id,
  108. prtd->vol_pan.volume,
  109. 0, POPP);
  110. break;
  111. default:
  112. MM_DBG("Unknown Event\n");
  113. break;
  114. }
  115. }
  116. static void alsa_in_listener(u32 evt_id, union auddev_evt_data *evt_payload,
  117. void *private_data)
  118. {
  119. struct msm_audio *prtd = (struct msm_audio *) private_data;
  120. MM_DBG("evt_id = 0x%8x\n", evt_id);
  121. switch (evt_id) {
  122. case AUDDEV_EVT_DEV_RDY: {
  123. MM_DBG("AUDDEV_EVT_DEV_RDY\n");
  124. prtd->source |= (0x1 << evt_payload->routing_id);
  125. if ((prtd->running == 1) && (prtd->enabled == 1))
  126. alsa_in_record_config(prtd, 1);
  127. break;
  128. }
  129. case AUDDEV_EVT_DEV_RLS: {
  130. MM_DBG("AUDDEV_EVT_DEV_RLS\n");
  131. prtd->source &= ~(0x1 << evt_payload->routing_id);
  132. if (!prtd->running || !prtd->enabled)
  133. break;
  134. /* Turn off as per source */
  135. if (prtd->source)
  136. alsa_in_record_config(prtd, 1);
  137. else
  138. /* Turn off all */
  139. alsa_in_record_config(prtd, 0);
  140. break;
  141. }
  142. case AUDDEV_EVT_FREQ_CHG: {
  143. MM_DBG("Encoder Driver got sample rate change event\n");
  144. MM_DBG("sample rate %d\n", evt_payload->freq_info.sample_rate);
  145. MM_DBG("dev_type %d\n", evt_payload->freq_info.dev_type);
  146. MM_DBG("acdb_dev_id %d\n", evt_payload->freq_info.acdb_dev_id);
  147. if (prtd->running == 1) {
  148. /* Stop Recording sample rate does not match
  149. with device sample rate */
  150. if (evt_payload->freq_info.sample_rate !=
  151. prtd->samp_rate) {
  152. alsa_in_record_config(prtd, 0);
  153. prtd->abort = 1;
  154. wake_up(&the_locks.read_wait);
  155. }
  156. }
  157. break;
  158. }
  159. default:
  160. MM_DBG("Unknown Event\n");
  161. break;
  162. }
  163. }
  164. static void msm_pcm_enqueue_data(struct snd_pcm_substream *substream)
  165. {
  166. struct snd_pcm_runtime *runtime = substream->runtime;
  167. struct msm_audio *prtd = runtime->private_data;
  168. unsigned int period_size;
  169. MM_DBG("prtd->out_tail =%d mmap_flag=%d\n",
  170. prtd->out_tail, prtd->mmap_flag);
  171. period_size = snd_pcm_lib_period_bytes(substream);
  172. alsa_dsp_send_buffer(prtd, prtd->out_tail, period_size);
  173. prtd->out_tail ^= 1;
  174. ++copy_count;
  175. prtd->period++;
  176. if (unlikely(prtd->period >= runtime->periods))
  177. prtd->period = 0;
  178. }
  179. static void event_handler(void *data)
  180. {
  181. struct msm_audio *prtd = data;
  182. MM_DBG("\n");
  183. snd_pcm_period_elapsed(prtd->substream);
  184. if (prtd->mmap_flag) {
  185. if (prtd->dir == SNDRV_PCM_STREAM_CAPTURE)
  186. return;
  187. if (!prtd->stopped)
  188. msm_pcm_enqueue_data(prtd->substream);
  189. else
  190. prtd->out_needed++;
  191. }
  192. }
  193. static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream)
  194. {
  195. struct snd_pcm_runtime *runtime = substream->runtime;
  196. struct msm_audio *prtd = runtime->private_data;
  197. MM_DBG("\n");
  198. prtd->pcm_size = snd_pcm_lib_buffer_bytes(substream);
  199. prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
  200. prtd->pcm_irq_pos = 0;
  201. prtd->pcm_buf_pos = 0;
  202. if (prtd->enabled)
  203. return 0;
  204. MM_DBG("\n");
  205. /* rate and channels are sent to audio driver */
  206. prtd->out_sample_rate = runtime->rate;
  207. prtd->out_channel_mode = runtime->channels;
  208. prtd->data = prtd->substream->dma_buffer.area;
  209. prtd->phys = prtd->substream->dma_buffer.addr;
  210. prtd->out[0].data = prtd->data + 0;
  211. prtd->out[0].addr = prtd->phys + 0;
  212. prtd->out[0].size = BUFSZ;
  213. prtd->out[1].data = prtd->data + BUFSZ;
  214. prtd->out[1].addr = prtd->phys + BUFSZ;
  215. prtd->out[1].size = BUFSZ;
  216. if (prtd->enabled | !(prtd->mmap_flag))
  217. return 0;
  218. prtd->out[0].used = prtd->pcm_count;
  219. prtd->out[1].used = prtd->pcm_count;
  220. mutex_lock(&the_locks.lock);
  221. alsa_audio_configure(prtd);
  222. mutex_unlock(&the_locks.lock);
  223. return 0;
  224. }
  225. static int msm_pcm_capture_prepare(struct snd_pcm_substream *substream)
  226. {
  227. struct snd_pcm_runtime *runtime = substream->runtime;
  228. struct msm_audio *prtd = runtime->private_data;
  229. int ret = 0;
  230. uint32_t freq;
  231. MM_DBG("\n");
  232. prtd->pcm_size = snd_pcm_lib_buffer_bytes(substream);
  233. prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
  234. prtd->pcm_irq_pos = 0;
  235. prtd->pcm_buf_pos = 0;
  236. /* rate and channels are sent to audio driver */
  237. prtd->type = ENC_TYPE_WAV;
  238. prtd->samp_rate = runtime->rate;
  239. prtd->channel_mode = (runtime->channels - 1);
  240. prtd->buffer_size = prtd->channel_mode ? STEREO_DATA_SIZE : \
  241. MONO_DATA_SIZE;
  242. if (prtd->enabled)
  243. return 0;
  244. freq = prtd->samp_rate;
  245. prtd->data = prtd->substream->dma_buffer.area;
  246. prtd->phys = prtd->substream->dma_buffer.addr;
  247. MM_DBG("prtd->data =%08x\n", (unsigned int)prtd->data);
  248. MM_DBG("prtd->phys =%08x\n", (unsigned int)prtd->phys);
  249. mutex_lock(&the_locks.lock);
  250. ret = alsa_audio_configure(prtd);
  251. mutex_unlock(&the_locks.lock);
  252. if (ret)
  253. return ret;
  254. ret = wait_event_interruptible(the_locks.enable_wait,
  255. prtd->running != 0);
  256. MM_DBG("state prtd->running = %d ret = %d\n", prtd->running, ret);
  257. if (prtd->running == 0)
  258. ret = -ENODEV;
  259. else
  260. ret = 0;
  261. prtd->enabled = 1;
  262. return ret;
  263. }
  264. static int msm_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
  265. {
  266. struct snd_pcm_runtime *runtime = substream->runtime;
  267. struct msm_audio *prtd = runtime->private_data;
  268. unsigned long flag = 0;
  269. int ret = 0;
  270. MM_DBG("\n");
  271. switch (cmd) {
  272. case SNDRV_PCM_TRIGGER_START:
  273. case SNDRV_PCM_TRIGGER_RESUME:
  274. case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  275. if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE)
  276. || !prtd->mmap_flag)
  277. break;
  278. if (!prtd->out_needed) {
  279. prtd->stopped = 0;
  280. break;
  281. }
  282. spin_lock_irqsave(&the_locks.write_dsp_lock, flag);
  283. if (prtd->running == 1) {
  284. if (prtd->stopped == 1) {
  285. prtd->stopped = 0;
  286. prtd->period = 0;
  287. if (prtd->pcm_irq_pos == 0) {
  288. prtd->out_tail = 0;
  289. msm_pcm_enqueue_data(prtd->substream);
  290. prtd->out_needed--;
  291. } else {
  292. prtd->out_tail = 1;
  293. msm_pcm_enqueue_data(prtd->substream);
  294. prtd->out_needed--;
  295. }
  296. if (prtd->out_needed) {
  297. prtd->out_tail ^= 1;
  298. msm_pcm_enqueue_data(prtd->substream);
  299. prtd->out_needed--;
  300. }
  301. }
  302. }
  303. spin_unlock_irqrestore(&the_locks.write_dsp_lock, flag);
  304. break;
  305. case SNDRV_PCM_TRIGGER_STOP:
  306. case SNDRV_PCM_TRIGGER_SUSPEND:
  307. case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  308. if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE)
  309. || !prtd->mmap_flag)
  310. break;
  311. prtd->stopped = 1;
  312. break;
  313. default:
  314. ret = -EINVAL;
  315. break;
  316. }
  317. return ret;
  318. }
  319. struct msm_audio_event_callbacks snd_msm_audio_ops = {
  320. .playback = event_handler,
  321. .capture = event_handler,
  322. };
  323. static int msm_pcm_open(struct snd_pcm_substream *substream)
  324. {
  325. struct snd_pcm_runtime *runtime = substream->runtime;
  326. struct msm_audio *prtd;
  327. int ret = 0;
  328. int i = 0;
  329. int session_attrb, sessionid;
  330. MM_DBG("\n");
  331. prtd = kzalloc(sizeof(struct msm_audio), GFP_KERNEL);
  332. if (prtd == NULL) {
  333. ret = -ENOMEM;
  334. return ret;
  335. }
  336. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  337. if (prtd->opened) {
  338. kfree(prtd);
  339. return -EBUSY;
  340. }
  341. runtime->hw = msm_pcm_playback_hardware;
  342. prtd->dir = SNDRV_PCM_STREAM_PLAYBACK;
  343. prtd->eos_ack = 0;
  344. prtd->session_id = HOSTPCM_STREAM_ID;
  345. prtd->device_events = AUDDEV_EVT_DEV_RDY |
  346. AUDDEV_EVT_STREAM_VOL_CHG |
  347. AUDDEV_EVT_DEV_RLS;
  348. prtd->source = msm_snddev_route_dec(prtd->session_id);
  349. MM_ERR("Register device event listener\n");
  350. ret = auddev_register_evt_listner(prtd->device_events,
  351. AUDDEV_CLNT_DEC, prtd->session_id,
  352. alsa_out_listener, (void *) prtd);
  353. if (ret) {
  354. MM_ERR("failed to register device event listener\n");
  355. goto evt_error;
  356. }
  357. } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
  358. runtime->hw = msm_pcm_capture_hardware;
  359. prtd->dir = SNDRV_PCM_STREAM_CAPTURE;
  360. session_attrb = ENC_TYPE_WAV;
  361. sessionid = audpreproc_aenc_alloc(session_attrb,
  362. &prtd->module_name, &prtd->queue_id);
  363. if (sessionid < 0) {
  364. MM_ERR("AUDREC not available\n");
  365. kfree(prtd);
  366. return -ENODEV;
  367. }
  368. prtd->session_id = sessionid;
  369. MM_DBG("%s\n", prtd->module_name);
  370. ret = msm_adsp_get(prtd->module_name, &prtd->audrec,
  371. &alsa_audrec_adsp_ops, prtd);
  372. if (ret < 0) {
  373. audpreproc_aenc_free(prtd->session_id);
  374. kfree(prtd);
  375. return -ENODEV;
  376. }
  377. prtd->abort = 0;
  378. prtd->device_events = AUDDEV_EVT_DEV_RDY | AUDDEV_EVT_DEV_RLS |
  379. AUDDEV_EVT_FREQ_CHG;
  380. prtd->source = msm_snddev_route_enc(prtd->session_id);
  381. MM_ERR("Register device event listener\n");
  382. ret = auddev_register_evt_listner(prtd->device_events,
  383. AUDDEV_CLNT_ENC, prtd->session_id,
  384. alsa_in_listener, (void *) prtd);
  385. if (ret) {
  386. MM_ERR("failed to register device event listener\n");
  387. audpreproc_aenc_free(prtd->session_id);
  388. msm_adsp_put(prtd->audrec);
  389. goto evt_error;
  390. }
  391. }
  392. prtd->substream = substream;
  393. ret = snd_pcm_hw_constraint_list(runtime, 0,
  394. SNDRV_PCM_HW_PARAM_RATE,
  395. &constraints_sample_rates);
  396. if (ret < 0)
  397. MM_ERR("snd_pcm_hw_constraint_list failed\n");
  398. /* Ensure that buffer size is a multiple of period size */
  399. ret = snd_pcm_hw_constraint_integer(runtime,
  400. SNDRV_PCM_HW_PARAM_PERIODS);
  401. if (ret < 0)
  402. MM_ERR("snd_pcm_hw_constraint_integer failed\n");
  403. prtd->ops = &snd_msm_audio_ops;
  404. prtd->out[0].used = BUF_INVALID_LEN;
  405. prtd->out[1].used = 0;
  406. prtd->out_head = 1; /* point to second buffer on startup */
  407. prtd->out_tail = 0;
  408. prtd->dsp_cnt = 0;
  409. prtd->in_head = 0;
  410. prtd->in_tail = 0;
  411. prtd->in_count = 0;
  412. prtd->out_needed = 0;
  413. for (i = 0; i < FRAME_NUM; i++) {
  414. prtd->in[i].size = 0;
  415. prtd->in[i].read = 0;
  416. }
  417. prtd->vol_pan.volume = 0x2000;
  418. prtd->vol_pan.pan = 0x0;
  419. prtd->opened = 1;
  420. runtime->private_data = prtd;
  421. copy_count = 0;
  422. return 0;
  423. evt_error:
  424. kfree(prtd);
  425. return ret;
  426. }
  427. static int msm_pcm_playback_copy(struct snd_pcm_substream *substream, int a,
  428. snd_pcm_uframes_t hwoff, void __user *buf, snd_pcm_uframes_t frames)
  429. {
  430. int ret = 0;
  431. int fbytes = 0;
  432. struct snd_pcm_runtime *runtime = substream->runtime;
  433. struct msm_audio *prtd = runtime->private_data;
  434. fbytes = frames_to_bytes(runtime, frames);
  435. MM_DBG("%d\n", fbytes);
  436. ret = alsa_send_buffer(prtd, buf, fbytes, NULL);
  437. ++copy_count;
  438. prtd->pcm_buf_pos += fbytes;
  439. if (copy_count == 1) {
  440. mutex_lock(&the_locks.lock);
  441. ret = alsa_audio_configure(prtd);
  442. mutex_unlock(&the_locks.lock);
  443. }
  444. return ret;
  445. }
  446. static int msm_pcm_playback_close(struct snd_pcm_substream *substream)
  447. {
  448. struct snd_pcm_runtime *runtime = substream->runtime;
  449. struct msm_audio *prtd = runtime->private_data;
  450. int ret = 0;
  451. MM_DBG("\n");
  452. if ((!prtd->mmap_flag) && prtd->enabled) {
  453. ret = wait_event_interruptible(the_locks.eos_wait,
  454. (!(prtd->out[0].used) && !(prtd->out[1].used)));
  455. if (ret < 0)
  456. goto done;
  457. }
  458. /* PCM DMAMISS message is sent only once in
  459. * hpcm interface. So, wait for buffer complete
  460. * and teos flag.
  461. */
  462. if (prtd->enabled)
  463. ret = wait_event_interruptible(the_locks.eos_wait,
  464. prtd->eos_ack);
  465. done:
  466. alsa_audio_disable(prtd);
  467. auddev_unregister_evt_listner(AUDDEV_CLNT_DEC, prtd->session_id);
  468. kfree(prtd);
  469. return 0;
  470. }
  471. static int msm_pcm_capture_copy(struct snd_pcm_substream *substream,
  472. int channel, snd_pcm_uframes_t hwoff, void __user *buf,
  473. snd_pcm_uframes_t frames)
  474. {
  475. int ret = 0, rc1 = 0, rc2 = 0;
  476. int fbytes = 0;
  477. struct snd_pcm_runtime *runtime = substream->runtime;
  478. struct msm_audio *prtd = substream->runtime->private_data;
  479. int monofbytes = 0;
  480. char *bufferp = NULL;
  481. if (prtd->abort)
  482. return -EPERM;
  483. fbytes = frames_to_bytes(runtime, frames);
  484. MM_DBG("%d\n", fbytes);
  485. monofbytes = fbytes / 2;
  486. if (runtime->channels == 2) {
  487. ret = alsa_buffer_read(prtd, buf, fbytes, NULL);
  488. } else {
  489. bufferp = buf;
  490. rc1 = alsa_buffer_read(prtd, bufferp, monofbytes, NULL);
  491. bufferp = buf + monofbytes ;
  492. rc2 = alsa_buffer_read(prtd, bufferp, monofbytes, NULL);
  493. ret = rc1 + rc2;
  494. }
  495. prtd->pcm_buf_pos += fbytes;
  496. MM_DBG("prtd->pcm_buf_pos =%d, prtd->mmap_flag =%d\n",
  497. prtd->pcm_buf_pos, prtd->mmap_flag);
  498. return ret;
  499. }
  500. static int msm_pcm_capture_close(struct snd_pcm_substream *substream)
  501. {
  502. struct snd_pcm_runtime *runtime = substream->runtime;
  503. struct msm_audio *prtd = runtime->private_data;
  504. int ret = 0;
  505. MM_DBG("\n");
  506. ret = msm_snddev_withdraw_freq(prtd->session_id,
  507. SNDDEV_CAP_TX, AUDDEV_CLNT_ENC);
  508. MM_DBG("msm_snddev_withdraw_freq\n");
  509. auddev_unregister_evt_listner(AUDDEV_CLNT_ENC, prtd->session_id);
  510. prtd->abort = 0;
  511. wake_up(&the_locks.enable_wait);
  512. alsa_audrec_disable(prtd);
  513. audpreproc_aenc_free(prtd->session_id);
  514. msm_adsp_put(prtd->audrec);
  515. kfree(prtd);
  516. return 0;
  517. }
  518. static int msm_pcm_copy(struct snd_pcm_substream *substream, int a,
  519. snd_pcm_uframes_t hwoff, void __user *buf, snd_pcm_uframes_t frames)
  520. {
  521. int ret = 0;
  522. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  523. ret = msm_pcm_playback_copy(substream, a, hwoff, buf, frames);
  524. else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
  525. ret = msm_pcm_capture_copy(substream, a, hwoff, buf, frames);
  526. return ret;
  527. }
  528. static int msm_pcm_close(struct snd_pcm_substream *substream)
  529. {
  530. int ret = 0;
  531. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  532. ret = msm_pcm_playback_close(substream);
  533. else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
  534. ret = msm_pcm_capture_close(substream);
  535. return ret;
  536. }
  537. static int msm_pcm_prepare(struct snd_pcm_substream *substream)
  538. {
  539. int ret = 0;
  540. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  541. ret = msm_pcm_playback_prepare(substream);
  542. else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
  543. ret = msm_pcm_capture_prepare(substream);
  544. return ret;
  545. }
  546. static snd_pcm_uframes_t msm_pcm_pointer(struct snd_pcm_substream *substream)
  547. {
  548. struct snd_pcm_runtime *runtime = substream->runtime;
  549. struct msm_audio *prtd = runtime->private_data;
  550. MM_DBG("pcm_irq_pos = %d\n", prtd->pcm_irq_pos);
  551. if (prtd->pcm_irq_pos == prtd->pcm_size)
  552. prtd->pcm_irq_pos = 0;
  553. return bytes_to_frames(runtime, (prtd->pcm_irq_pos));
  554. }
  555. int msm_pcm_mmap(struct snd_pcm_substream *substream,
  556. struct vm_area_struct *vma)
  557. {
  558. struct snd_pcm_runtime *runtime = substream->runtime;
  559. struct msm_audio *prtd = runtime->private_data;
  560. prtd->out_head = 0; /* point to First buffer on startup */
  561. prtd->mmap_flag = 1;
  562. runtime->dma_bytes = snd_pcm_lib_period_bytes(substream)*2;
  563. dma_mmap_coherent(substream->pcm->card->dev, vma,
  564. runtime->dma_area,
  565. runtime->dma_addr,
  566. runtime->dma_bytes);
  567. return 0;
  568. }
  569. int msm_pcm_hw_params(struct snd_pcm_substream *substream,
  570. struct snd_pcm_hw_params *params)
  571. {
  572. snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
  573. return 0;
  574. }
  575. static struct snd_pcm_ops msm_pcm_ops = {
  576. .open = msm_pcm_open,
  577. .copy = msm_pcm_copy,
  578. .hw_params = msm_pcm_hw_params,
  579. .close = msm_pcm_close,
  580. .ioctl = snd_pcm_lib_ioctl,
  581. .prepare = msm_pcm_prepare,
  582. .trigger = msm_pcm_trigger,
  583. .pointer = msm_pcm_pointer,
  584. .mmap = msm_pcm_mmap,
  585. };
  586. static int pcm_preallocate_buffer(struct snd_pcm *pcm,
  587. int stream)
  588. {
  589. struct snd_pcm_substream *substream = pcm->streams[stream].substream;
  590. struct snd_dma_buffer *buf = &substream->dma_buffer;
  591. size_t size;
  592. if (!stream)
  593. size = PLAYBACK_DMASZ;
  594. else
  595. size = CAPTURE_DMASZ;
  596. buf->dev.type = SNDRV_DMA_TYPE_DEV;
  597. buf->dev.dev = pcm->card->dev;
  598. buf->private_data = NULL;
  599. buf->area = dma_alloc_coherent(pcm->card->dev, size,
  600. &buf->addr, GFP_KERNEL);
  601. if (!buf->area)
  602. return -ENOMEM;
  603. buf->bytes = size;
  604. return 0;
  605. }
  606. static void msm_pcm_free_buffers(struct snd_pcm *pcm)
  607. {
  608. struct snd_pcm_substream *substream;
  609. struct snd_dma_buffer *buf;
  610. int stream;
  611. for (stream = 0; stream < 2; stream++) {
  612. substream = pcm->streams[stream].substream;
  613. if (!substream)
  614. continue;
  615. buf = &substream->dma_buffer;
  616. if (!buf->area)
  617. continue;
  618. dma_free_coherent(pcm->card->dev, buf->bytes,
  619. buf->area, buf->addr);
  620. buf->area = NULL;
  621. }
  622. }
  623. static int msm_pcm_new(struct snd_soc_pcm_runtime *rtd)
  624. {
  625. int ret = 0;
  626. struct snd_card *card = rtd->card->snd_card;
  627. struct snd_pcm *pcm = rtd->pcm;
  628. ret = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_PLAYBACK, 1);
  629. if (ret)
  630. return ret;
  631. ret = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_CAPTURE, 1);
  632. if (ret)
  633. return ret;
  634. snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &msm_pcm_ops);
  635. snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &msm_pcm_ops);
  636. if (!card->dev->coherent_dma_mask)
  637. card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
  638. ret = pcm_preallocate_buffer(pcm,
  639. SNDRV_PCM_STREAM_PLAYBACK);
  640. if (ret)
  641. return ret;
  642. ret = pcm_preallocate_buffer(pcm,
  643. SNDRV_PCM_STREAM_CAPTURE);
  644. if (ret)
  645. msm_pcm_free_buffers(pcm);
  646. return ret;
  647. }
  648. struct snd_soc_platform_driver msm_soc_platform = {
  649. .ops = &msm_pcm_ops,
  650. .pcm_new = msm_pcm_new,
  651. .pcm_free = msm_pcm_free_buffers,
  652. };
  653. EXPORT_SYMBOL(msm_soc_platform);
  654. static __devinit int msm_pcm_probe(struct platform_device *pdev)
  655. {
  656. return snd_soc_register_platform(&pdev->dev,
  657. &msm_soc_platform);
  658. }
  659. static int msm_pcm_remove(struct platform_device *pdev)
  660. {
  661. snd_soc_unregister_platform(&pdev->dev);
  662. return 0;
  663. }
  664. static struct platform_driver msm_pcm_driver = {
  665. .driver = {
  666. .name = "msm-dsp-audio",
  667. .owner = THIS_MODULE,
  668. },
  669. .probe = msm_pcm_probe,
  670. .remove = __devexit_p(msm_pcm_remove),
  671. };
  672. static int __init msm_soc_platform_init(void)
  673. {
  674. return platform_driver_register(&msm_pcm_driver);
  675. }
  676. module_init(msm_soc_platform_init);
  677. static void __exit msm_soc_platform_exit(void)
  678. {
  679. platform_driver_unregister(&msm_pcm_driver);
  680. }
  681. module_exit(msm_soc_platform_exit);
  682. MODULE_DESCRIPTION("PCM module platform driver");
  683. MODULE_LICENSE("GPL v2");